我需要创建两个子进程,每个子进程在fork之后调用execvp
,并且这些可执行文件之间共享POSIX信号量。
我需要创建一个共享内存还是只实现命名信号量就可以了?
我从以下链接中得到了两个答案:
但是我对如何进行实现感到困惑。
我需要创建两个子进程,每个子进程在fork之后调用execvp
,并且这些可执行文件之间共享POSIX信号量。
我需要创建一个共享内存还是只实现命名信号量就可以了?
我从以下链接中得到了两个答案:
但是我对如何进行实现感到困惑。
#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 semaphore\n", (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;
}
你可以通过在一个共同的头文件中定义信号量名称并将其包含在每个程序的代码中,从而消除在两个源文件之间同步信号量名称的需要。
请注意,在此示例中错误处理不是理想的(它只是作为说明),有很大的改进空间。它只是为了确保当你决定更改此示例以满足你的需求时,不要忘记进行适当的错误处理。
execvp
。 - pilcrowshm_open(3)
+ sem_init(3)
),然后让执行的程序代码调用shm_open(3)
以访问共享内存段(并因此获得对信号量的引用)。 - Filipe Gonçalves*_open
(通过继承资源,这无法跨越“exec”完成)。 - pilcrow共享内存方法在这里也适用,唯一需要注意的是父进程必须初始化共享内存。 此代码似乎有一个错误,即除了两个子进程外,父进程还将分叉出3个子进程。这里应该有一个break语句。
if (pids[i] == 0) {
if (execl(CHILD_PROGRAM, CHILD_PROGRAM, NULL) < 0) {
perror("execl(2) failed");
exit(EXIT_FAILURE);
}
break; //this is required
}
sem_unlink
之前,该信号量将一直存在。 - Jason