是否可以fork / exec并保证一个在另一个之前启动?

时间:2011-08-31 19:55:01

标签: c exec fork parallel-processing

就像标题所说的那样。我有一段代码如下:

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可能是我所寻求的最接近的东西,但下面提出的所有解决方案都会或多或少地起作用。

5 个答案:

答案 0 :(得分:5)

互斥锁应该能够解决这个问题。在调用fork之前锁定互斥锁并使第一个函数正常执行,而第二个函数尝试声明互斥锁。第一个应该在完成后解锁互斥锁,第二个将等到它被释放。

编辑:互斥锁必须位于两个进程的共享内存段

答案 1 :(得分:5)

此问题通常由mutexsemaphore解决。例如:

// 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)),以便它工作

这可以确保childfnparentfn中只有一个会在任何给定时间执行,但它们可以按任意顺序运行。如果你需要先运行一个特定的运行,请以1为1而不是0来启动信号量,并且需要先运行的函数不等待信号量(但在完成时仍然会发送到它)。您也可以使用具有不同语义的condition variable

答案 2 :(得分:3)

最安全的方法是使用(命名)管道或套接字。一方写信,另一方写。读者无法阅读尚未写入的内容。

答案 3 :(得分:1)

使用信号量确保一个信号量在另一个信号量之前启动。

答案 4 :(得分:0)

您可以使用原子变量。在fork / thread / exec之前将它设置为零,让第一个进程在进入函数之前(或更好,之后)将其设置为1,并让第二个进程等待(flag == 0)。