我有一个问题,我想做一个fork例如一个20processes的fork,这个fork创建,不应该做任何事情,直到最后一个没有创建,我想用信号量做,我怎么能实现它?
for (i=0; i<20; i++) {
switch (fork()) {
case: -1:
exit(EXIT_FAILURE);
case 0:
execve(....);
exit(EXIT_FAILURE);
default:
printf ("Child Created!");
}
}
答案 0 :(得分:3)
这是你的作业。你以后可以付钱给我。
#include <semaphore.h>
#include <sys/mman.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
sem_t *sem;
if(MAP_FAILED==(sem=mmap(0, sizeof(*sem), PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0)))
{ perror("mmap"); exit(EXIT_FAILURE); }
if(0>sem_init(sem, 1/*shared*/, 0/*init val*/))
{ perror("sem_init"); exit(EXIT_FAILURE); }
for(int i=0; i<20; i++){
switch(fork()){
case -1: perror("fork"); /*you'll need to kill the children here*/
exit(EXIT_FAILURE);
case 0:
puts("waiting");
sem_wait(sem);
puts("running");
exit(0);
default:
puts("Child created");
}
}
puts("done forking. signalling children");
usleep(1000000);
for(int i=0; i<20; i++)
sem_post(sem);
}
这个想法很简单。将(必然的,共享的)信号量初始化为零,并使每个孩子在它做它之前等待它。
当您在父母中完成分叉时,您会向信号量发送20次,以便每个孩子的sem_wait
来电完成。
与SysV信号量相同:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
//the manpage says we should define this union (as follows)
union semun {
int val; /* Value for SETVAL */
struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */
unsigned short *array; /* Array for GETALL, SETALL */
struct seminfo *__buf; /* Buffer for IPC_INFO
(Linux-specific) */
};
int main()
{
key_t key;
char tmpl[]="/tmp/XXXXXX";
{
int tmpfd;
if(0>(tmpfd = mkstemp(tmpl)))
{ perror("mkstemp"); exit(EXIT_FAILURE); }
close(tmpfd);
}
//Get a key
puts(tmpl);
key=ftok(tmpl, 'A');
int sem;
int ec = EXIT_SUCCESS;
if(0>(sem = semget(key, 1 /*1 sem*/, IPC_CREAT|IPC_EXCL|0600)))
{ perror("semget"); goto fail; }
if(0>semctl(sem, 0 /*ix*/, SETVAL, (union semun){ .val=0 }))
{ perror("sem init"); goto fail; }
for(int i=0; i<20; i++){
switch(fork()){
case -1: { perror("fork"); /*you'll need to kill the children here*/ exit(EXIT_FAILURE); }
case 0:
puts("waiting");
semop(sem, (struct sembuf[1]){{ .sem_op=-1 }}, 1);
puts("running");
exit(0);
default:
puts("Child created");
}
}
puts("done forking. signalling children");
usleep(1000000);
//can up it by 20 in one go
semop(sem, (struct sembuf[1]){{ .sem_op=+20 }}, 1);
goto success;
fail: ec = EXIT_FAILURE;
success:
semctl(sem, 0, IPC_RMID);
unlink(tmpl);
exit(ec);
}
在这里你必须围绕SysV IPC API丑陋和设置基于文件的密钥的需要跳舞,但是,作为奖励,你可以一次性将信号量增加20倍。