以下示例是主观察者进程。图 5–3 显示了主观察进程的资源控制。
换行符在 /etc/project 文件中是无效的。此处显示的换行符仅允许示例显示在列显页或显示页上。/etc/project 文件中的每一项都必须占用单独的一行。
该示例的要点包括以下内容:
由于任务的限制具有权限,因此应用程序无法更改限制,也无法指定操作(如信号)。主进程通过为任务建立与基本资源控制相同的资源控制解决了此问题。主进程对资源使用相同的值或稍小的值,但执行不同的操作(信号 = XRES)。主进程将创建一个线程以等待此信号。
rctlblk 是不透明的。需要动态分配结构。
请注意,sigwait(2) 要求在创建线程之前阻塞所有的信号。
线程将调用 sigwait(2) 来阻塞信号。如果 sigwait() 返回 SIGXRES 信号,则线程将通知主进程的子进程适当减少正在使用的 LWP 的数目。此外,还应该使用每个子进程中的线程以类似方式为每个子进程建模,以等待此信号并适当调整其进程的 LWP 使用情况。
rctlblk_t *mlwprcb; sigset_t smask; /* Omit return value checking/error processing to keep code sample short */ /* First, install a RCPRIV_BASIC, v=1000, signal=SIGXRES rctl */ mlwprcb = calloc(1, rctlblk_size()); /* rctl blocks are opaque: */ rctlblk_set_value(mlwprcb, 1000); rctlblk_set_privilege(mlwprcb, RCPRIV_BASIC); rctlblk_set_local_action(mlwprcb, RCTL_LOCAL_SIGNAL, SIGXRES); if (setrctl("task.max-lwps", NULL, mlwprcb, RCTL_INSERT) == -1) { perror("setrctl"); exit (1); } /* Now, create the thread which waits for the signal */ sigemptyset(&smask); sigaddset(&smask, SIGXRES); thr_sigsetmask(SIG_BLOCK, &smask, NULL); thr_create(NULL, 0, sigthread, (void *)SIGXRES, THR_DETACHED, NULL)); /* Omit return value checking/error processing to keep code sample short */ void *sigthread(void *a) { int sig = (int)a; int rsig; sigset_t sset; sigemptyset(&sset); sigaddset(&sset, sig); while (1) { rsig = sigwait(&sset); if (rsig == SIGXRES) { notify_all_children(); /* e.g. sigsend(P_PID, child_pid, SIGXRES); */ } } }
以下示例列出了特定资源控制 task.max-lwps 的所有值-操作对。该示例的要点是 getrctl(2) 使用两个资源控制块,并返回 RCTL_NEXT 标志的资源控制块。要在所有的资源控制块中迭代,请使用 rcb_tmp rctl 块反复交换此处显示的资源控制块值。
rctlblk_t *rcb1, *rcb2, *rcb_tmp; ... /* Omit return value checking/error processing to keep code sample short */ rcb1 = calloc(1, rctlblk_size()); /* rctl blocks are opaque: */ /* "rctlblk_t rcb" does not work */ rcb2 = calloc(1, rctlblk_size()); getrctl("task.max-lwps", NULL, rcb1, RCTL_FIRST); while (1) { print_rctl(rcb1); rcb_tmp = rcb2; rcb2 = rcb1; rcb1 = rcb_tmp; /* swap rcb1 with rcb2 */ if (getrctl("task.max-lwps", rcb2, rcb1, RCTL_NEXT) == -1) { if (errno == ENOENT) { break; } else { perror("getrctl"); exit (1); } } }
该示例类似于设置 pool.comment 属性并添加新属性中显示的示例。
请使用 bcopy(),而不要使用列出特定资源控制的所有值-操作对中的缓冲区交换。
要更改资源控制值,在调用 setrctl() 时请使用 RCTL_REPLACE 标志。新的资源控制块除了使用新的控制值以外,与原有的资源控制块相同。
rctlblk_set_value(blk1, nshares); if (setrctl("project.cpu-shares", blk2, blk1, RCTL_REPLACE) != 0)
该示例将获取项目的 CPU 份额分配 project.cpu-shares,并将其值更改为 nshares。
/* Omit return value checking/error processing to keep code sample short */ blk1 = malloc(rctlblk_size()); getrctl("project.cpu-shares", NULL, blk1, RCTL_FIRST); my_shares = rctlblk_get_value(blk1); printout_my_shares(my_shares); /* if privileged, do the following to */ /* change project.cpu-shares to "nshares" */ blk1 = malloc(rctlblk_size()); blk2 = malloc(rctlblk_size()); if (getrctl("project.cpu-shares", NULL, blk1, RCTL_FIRST) != 0) { perror("getrctl failed"); exit(1); } bcopy(blk1, blk2, rctlblk_size()); rctlblk_set_value(blk1, nshares); if (setrctl("project.cpu-shares", blk2, blk1, RCTL_REPLACE) != 0) { perror("setrctl failed"); exit(1); }
在以下示例中,应用程序设置了具有权限的限制 3000 LWP(可能没有超过)。 此外,应用程序还设置了基本限制 2000 LWP。 超过此限制时,系统会将 SIGXRES 发送到应用程序。 收到 SIGXRES 时,应用程序可能会将通知发送给其子进程,而该进程可能会减少进程使用或需要的 LWP 数目。
/* Omit return value and error checking */ #include <rctl.h> rctlblk_t *rcb1, *rcb2; /* * Resource control blocks are opaque * and must be explicitly allocated. */ rcb1 = calloc(rctlblk_size()); rcb2 = calloc(rctlblk_size()); /* Install an RCPRIV_PRIVILEGED, v=3000: do not allow more than 3000 LWPs */ rctlblk_set_value(rcb1, 3000); rctlblk_set_privilege(rcb1, RCPRIV_PRIVILEGED); rctlblk_set_local_action(rcb1, RCTL_LOCAL_DENY); setrctl("task.max-lwps", NULL, rcb1, RCTL_INSERT); /* Install an RCPRIV_BASIC, v=2000 to send SIGXRES when LWPs exceeds 2000 */ rctlblk_set_value(rcb2, 2000); rctlblk_set_privilege(rcb2, RCPRIV_BASIC); rctlblk_set_local_action(rcb2, RCTL_LOCAL_SIGNAL, SIGXRES); setrctl("task.max-lwps", NULL, rcb2, RCTL_INSERT);