我将再次需要您的帮助...
我正在尝试用C语言开发一个程序,该程序可以执行以下操作:
managerProcess
创建NUM_PROCESSES
Student
进程。
每个Student
进程一旦创建,就等待其他Student
进程被创建,直到创建的进程数为止。
创建所有Student
流程后,它们开始做自己的工作,这与该问题无关。
重要的事情:每个Student
进程必须具有相同的代码。
这是我写的一些代码:
pid_t run_child(Student s, int index, int (*function)(Student s, int index)){
pid_t p;
p = fork();
if (p == -1)
return -1;
else if (!p)
exit(function(s, index));
else
return p;
}
int child_process(Student s, int index){
//This printf is executed NUM_PROCESSES times
printf("Child Process %d has been created\n", getpid());
//Once reached this point each Process running this function will do other things
/*SOME OTHER CODE STUDENT PROCESSES EXECUTE*/
printf("%d Student Processes Created\n", NUM_PROCESSES);
return EXIT_SUCCESS;
}
最后main.c
个文件:
int main(int argc, char *argv[]){
pid_t child_pid[NUM_PROCESSES];
int child_status[NUM_PROCESSES];
int i;
int status;
status = EXIT_SUCCESS;
for (i = 0; i < NUM_PROCESSES; i++) {
Student s;
child_pid[i] = run_child(s, i, child_process);
if (child_pid[i] == -1) {
fprintf(stderr, "Cannot fork a child process: %s.\n", strerror(errno));
status = EXIT_FAILURE;
}
}
return status;
}
您可能会注意到,上面的代码创建了NUM_PROCESSES
Student
流程,这很好。
我想做的是每个Student
进程都等待所有NUM_PROCESSES
Student
进程的创建,然后它们才开始做其他事情。
如何使用下面开发的Semaphore
实现这一目标?
//Creates ONE Semaphore
int createSemaphore(key_t semaphoreKey){
int semaphoreId = semget(semaphoreKey, 1, 0666 | IPC_CREAT);
if(semaphoreId == -1){
printf(RED "Semaphore Creation failed\n"RESET);
return -1;
}
return semaphoreId;
}
//Creates a set of Semaphores with numSems Semaphores
int createSemaphoreSet(key_t semaphoreKey, int numSems){
int semaphoreId = semget(semaphoreKey, numSems, 0666 | IPC_CREAT);
if(semaphoreId == -1){
printf(RED "Semaphore Set Creation Failed\n" RESET);
return -1;
}
return semaphoreId;
}
//Decreases semaphores value by 1
void semaphoreWait(int semaphoreId, int semaphoreNumber){
struct sembuf buffer;
buffer.sem_num = semaphoreNumber;
buffer.sem_op = -1;
buffer.sem_flg = 0;
int done = semop(semaphoreId, &buffer, 1);
if(done == -1){
printf(RED "Wait on Semaphore %d failed\n" RESET, semaphoreNumber);
return;
}
}
//Increments semaphore's value by 1
void semaphoreSignal(int semaphoreId, int semaphoreNumber){
struct sembuf buffer;
buffer.sem_num = semaphoreNumber;
buffer.sem_op = 1;
buffer.sem_flg = 0;
int done = semop(semaphoreId, &buffer, 1);
if(done == -1){
printf(RED "semaphoreSignal Failed on Semaphore %d\n" RESET, semaphoreNumber);
return;
}
}
希望我已经清楚了。 非常感谢
答案 0 :(得分:1)
有了您使用的System-V信号量,一般方案将最好地像这样:
父进程通过semget()
创建或打开信号量,并通过semctl()
将其值初始化为0。
父母分叉了所有孩子。
每个孩子都通过semop()
对信号量执行一次递减运算。例如,
struct sembuf semops = { .sem_num = 0, .sem_op = -1 };
int result = semop(semid, &semops, 1);
每个孩子都会阻塞,直到可以执行此操作而不会使信号量的值为负。
父级使用semop()
通过子进程数来增加信号量的值。此信号量操作不会阻止,完成后,所有孩子都可以继续进行。
struct sembuf semops2 = { .sem_num = 0, .sem_op = NUM_PROCESSES };
int result2 = semop(semid, &semops2, 1);
还有信号灯操作的其他组合可以实现您描述的内容(以及可以用来执行其中一些信号的更现代的信号灯样式),但是我敢说以上内容为此类任务提供了标准的System-V习惯用法。