在多个进程之间共享POSIX信号量
我需要创建两个子进程,每个子进程调用execvp ater进行分叉,可执行文件在它们之间共享POSIX信号量.
我是否需要创建共享内存或仅实现命名信号量? 我从以下链接得到两个答案: > Do forked child processes use the same semaphore? 但我对如何继续实施感到困惑. 解决方法
这两种方法都有效.选择一个并继续使用它 – 虽然我个人更喜欢命名信号量,因为您不必处理内存分配和设置共享内存段.在我看来,创建和使用命名信号量的界面更友好. 使用命名信号量,在您的示例场景中,会发生以下情况: >使用sem_open(3)在父进程中创建和初始化信号量.给它一个众所周知的名称,儿童过程将知道;此名称用于查找系统中的信号量. 子进程使用众所周知的名称调用sem_open(3)来查找并获取对信号量的引用.一旦使用信号量完成一个过程,您需要使用sem_close(3)关闭它. 下面是我刚才描述的一个例子.父进程创建一个命名信号量,而forks执行2个子进程,每个进程查找并打开信号量,使用它来相互同步. 它假定父分叉并执行./sem_chld二进制文件.请记住,信号量的名称必须以正斜杠开头,后跟一个或多个不是斜杠的字符(请参阅man sem_overview).在此示例中,信号量的名称为/ semaphore_example. 这是父进程的代码: #include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <unistd.h> #include <semaphore.h> #include <sys/stat.h> #include <sys/types.h> #include <sys/wait.h> #define SEM_NAME "/semaphore_example" #define SEM_PERMS (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP) #define INITIAL_VALUE 1 #define CHILD_PROGRAM "./sem_chld" int main(void) { /* We initialize the semaphore counter to 1 (INITIAL_VALUE) */ sem_t *semaphore = sem_open(SEM_NAME,O_CREAT | O_EXCL,SEM_PERMS,INITIAL_VALUE); if (semaphore == SEM_FAILED) { perror("sem_open(3) error"); exit(EXIT_FAILURE); } /* Close the semaphore as we won't be using it in the parent process */ if (sem_close(semaphore) < 0) { perror("sem_close(3) failed"); /* We ignore possible sem_unlink(3) errors here */ sem_unlink(SEM_NAME); exit(EXIT_FAILURE); } pid_t pids[2]; size_t i; for (i = 0; i < sizeof(pids)/sizeof(pids[0]); i++) { if ((pids[i] = fork()) < 0) { perror("fork(2) failed"); exit(EXIT_FAILURE); } if (pids[i] == 0) { if (execl(CHILD_PROGRAM,CHILD_PROGRAM,NULL) < 0) { perror("execl(2) failed"); exit(EXIT_FAILURE); } } } for (i = 0; i < sizeof(pids)/sizeof(pids[0]); i++) if (waitpid(pids[i],NULL,0) < 0) perror("waitpid(2) failed"); if (sem_unlink(SEM_NAME) < 0) perror("sem_unlink(3) failed"); return 0; } 注意,在两个子节点终止后调用sem_unlink(3);虽然这不是必需的,但是如果之前调用它,则在父进程之间存在争用条件,取消链接信号量和启动并打开信号量的子进程.但是,一般情况下,只要您知道所有必需的进程都已打开信号量并且没有新进程需要查找它,您就可以取消链接. 这是sem_chld的代码,它只是一个小玩具程序,用于显示共享信号量的用法: #include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <semaphore.h> #include <unistd.h> #include <sys/stat.h> #include <sys/types.h> #define SEM_NAME "/semaphore_example" #define ITERS 10 int main(void) { sem_t *semaphore = sem_open(SEM_NAME,O_RDWR); if (semaphore == SEM_FAILED) { perror("sem_open(3) failed"); exit(EXIT_FAILURE); } int i; for (i = 0; i < ITERS; i++) { if (sem_wait(semaphore) < 0) { perror("sem_wait(3) failed on child"); continue; } printf("PID %ld acquired semaphoren",(long) getpid()); if (sem_post(semaphore) < 0) { perror("sem_post(3) error on child"); } sleep(1); } if (sem_close(semaphore) < 0) perror("sem_close(3) failed"); return 0; } 您可以通过在公共头文件中定义信号量名称并将其包含在每个程序的代码中来消除在两个源文件之间保持信号量名称同步的需要. 请注意,在此示例中错误处理并不理想(仅仅是说明性的),还有很大的改进空间.当您决定更改此示例以满足您的需求时,确保您不会忘记执行正确的错误处理. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |