[英]How to synchronize child processes with each other using semaphores?
我有N
個孩子需要在一個循環中做一些工作,同時彼此同步。 即,如果一個子進程處於其第 i 次迭代,則所有其他子進程都應處於第 i 次迭代。 我需要將它們與信號量同步,但我找不到如何做到這一點。 這是我寫的代碼:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/sem.h>
void sem_signal(int semid, int val) {
struct sembuf semaphore;
semaphore.sem_num = 0;
semaphore.sem_op = val;
semaphore.sem_flg = 0;
semop(semid, &semaphore, 1);
}
void sem_wait(int semid, int val) {
struct sembuf semaphore;
semaphore.sem_num = 0;
semaphore.sem_op = (-1 * val);
semaphore.sem_flg = 0;
semop(semid, &semaphore, 1);
}
int main() {
int sem_worker = semget(1, 1, 0700 | IPC_CREAT);
semctl(sem_worker, 0, SETVAL, 0);
int process_index = 0;
int N = 4, pid;
for (process_index = 0; process_index < N; process_index++) {
pid = fork();
if (pid == -1) {
printf("ERROR: cannot fork!\n");
return EXIT_FAILURE;
}
if (pid == 0)
break;
}
if (pid!=0) // parent
pause();
else {
int i = 0;
while (i < 3) {
printf("process %d: i: %d\n", process_index, i);
sem_signal(sem_worker, 1); // increase the semaphore by one
sem_wait(sem_worker, N); // wait for all the other childs
i += 1;
}
}
}
但是當我運行它時,它在第一次迭代后無法繼續。
process 0: i: 0
process 1: i: 0
process 3: i: 0
process 2: i: 0
process 0: i: 1
我明白為什么會這樣。 這是因為其中一個進程使信號量為 0 並繼續下一次迭代,但所有其他進程仍在等待。 那么我應該如何編寫代碼來解決這個問題呢?
PS:我從其他地方獲取了sem_signal
和sem_wait
函數,所以我不確定它是如何工作的,但我確信它們工作正常。 例如,如果我在父進程中寫入sem_wait(my_sem, num_of_children)
以等待所有子進程,並在子進程完成時將my_sem
增加 1,則它可以工作。
正如評論中提到的,您可以使用信號量創建屏障並使用它來同步您的流程。 您需要在共享 memory 中創建屏障,並為信號量的pshared
參數設置一個非零值以在進程之間共享它:
#include <semaphore.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/shm.h>
#include <signal.h>
#include <unistd.h>
typedef struct {
int n;
int count;
sem_t mutex;
sem_t turnstile;
sem_t turnstile2;
} barrier_t;
void init_barrier(barrier_t *barrier, int n)
{
barrier->n = n;
barrier->count = 0;
sem_init(&barrier->mutex, 1, 1); // second parameter is pshared
sem_init(&barrier->turnstile, 1, 0);
sem_init(&barrier->turnstile2, 1, 0);
}
void phase1(barrier_t *barrier)
{
sem_wait(&barrier->mutex);
if (++barrier->count == barrier->n) {
int i;
for (i = 0; i < barrier->n; i++) {
sem_post(&barrier->turnstile);
}
}
sem_post(&barrier->mutex);
sem_wait(&barrier->turnstile);
}
void phase2(barrier_t *barrier)
{
sem_wait(&barrier->mutex);
if (--barrier->count== 0) {
int i;
for (i = 0; i < barrier->n; i++) {
sem_post(&barrier->turnstile2);
}
}
sem_post(&barrier->mutex);
sem_wait(&barrier->turnstile2);
}
void wait_barrier(barrier_t *barrier)
{
phase1(barrier);
phase2(barrier);
}
int shmid, KEYSHM=123456;
int main(int argc, char const* argv[]) {
barrier_t* barrier;
shmid = shmget(KEYSHM, sizeof(barrier_t), 0700 | IPC_CREAT);
barrier = (barrier_t*) shmat(shmid, 0, 0);
int N = 4;
init_barrier(barrier, N);
shmdt(barrier);
int process_index, pid;
for (process_index = 0; process_index < N; process_index++) {
pid = fork();
if (pid == -1) {
printf("ERROR: cannot fork!\n");
return EXIT_FAILURE;
}
if (pid == 0)
break;
}
if (pid != 0) // parent
pause();
else {
int i = 0;
while (i < 3) {
barrier = (barrier_t*) shmat(shmid, 0, 0);
printf("process %d: i: %d\n", process_index, i);
i += 1;
wait_barrier(barrier);
shmdt(barrier);
}
if (process_index == 3){
kill(getppid(), SIGKILL);
}
}
}
process 0: i: 0 process 1: i: 0 process 2: i: 0 process 3: i: 0 process 2: i: 1 process 3: i: 1 process 0: i: 1 process 1: i: 1 process 3: i: 2 process 2: i: 2 process 0: i: 2 process 1: i: 2
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.