就像标题所说的那样。我有一段代码如下:
pid_t = p;
p = fork();
if (p == 0) {
childfn();
} else if (p > 0) {
parentfn();
} else {
// error
}
我想确保父或子在另一个之前执行(但不是从它们返回)各自的功能。
类似于对sleep()的调用可能会起作用,但任何标准都无法保证,并且只是利用操作系统调度程序的实现细节......这可能吗? vfork会工作吗?
编辑:两个函数都找到了system()调用,其中一个函数在另一个函数启动之前不会返回。所以要重新迭代:我需要确保父或子只调用它们各自的函数(但不返回,因为它们不会,这是下面提供的所有基于互斥锁的解决方案提供的)。有任何想法吗?抱歉缺乏清晰度。
edit2:有一个进程调用sched_yield和sleep,我似乎得到了非常可靠的结果。 vfork确实提供了我正在寻找的语义,但是对于我在子进程中可以做的事情有很多限制(我几乎只能调用exec)。所以,我发现了一些足够好的解决方案,但没有真正的解决方案。 vfork可能是我所寻求的最接近的东西,但下面提出的所有解决方案都会或多或少地起作用。
答案 0 :(得分:5)
互斥锁应该能够解决这个问题。在调用fork之前锁定互斥锁并使第一个函数正常执行,而第二个函数尝试声明互斥锁。第一个应该在完成后解锁互斥锁,第二个将等到它被释放。
编辑:互斥锁必须位于两个进程的共享内存段
答案 1 :(得分:5)
// Get a page of shared memory
int pagesize = getpagesize();
void *mem = mmap(NULL, pagesize, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0);
if(!mem)
{
perror("mmap");
return 1;
}
// Put the semaphore at the start of the shared page. The rest of the page
// is unused.
sem_t *sem = mem;
sem_init(sem, 1, 1);
pid_t p = fork();
if (p == 0) {
sem_wait(sem);
childfn();
sem_post(sem);
} else if (p > 0) {
sem_wait(sem);
parentfn();
sem_post(sem);
int status;
wait(&status);
sem_destroy(sem);
} else {
// error
}
// Clean up
munmap(mem, pagesize);
您还可以在共享内存区域中使用互斥锁,但是您需要确保使用非默认属性创建,并将进程共享属性称为共享(通过pthread_mutexattr_setpshared(&mutex, PTHREAD_PROCESS_SHARED)
),以便它工作
这可以确保childfn
或parentfn
中只有一个会在任何给定时间执行,但它们可以按任意顺序运行。如果你需要先运行一个特定的运行,请以1为1而不是0来启动信号量,并且需要先运行的函数不等待信号量(但在完成时仍然会发送到它)。您也可以使用具有不同语义的condition variable。
答案 2 :(得分:3)
最安全的方法是使用(命名)管道或套接字。一方写信,另一方写。读者无法阅读尚未写入的内容。
答案 3 :(得分:1)
使用信号量确保一个信号量在另一个信号量之前启动。
答案 4 :(得分:0)
您可以使用原子变量。在fork / thread / exec之前将它设置为零,让第一个进程在进入函数之前(或更好,之后)将其设置为1,并让第二个进程等待(flag == 0)。