Unix 由父进程的同一外壳上的多个子进程在标准输出上写入

Unix 由父进程的同一外壳上的多个子进程在标准输出上写入,unix,process,fork,stdout,read-write,Unix,Process,Fork,Stdout,Read Write,我有一个处理多个fork的进程,生成几个必须在stdout上写入的子进程。因此,不同子进程的消息可能会相互交叉。如何避免此问题?假设您有三个进程,每个进程都试图输出由四个字符和一个换行符组成的无限系列行: void four(char c); int main() { //insert your own error checking pid_t p0, p1, p2; #define PROC(pid,str) pid=fork(); if(0==pid) four(str);

我有一个处理多个fork的进程,生成几个必须在stdout上写入的子进程。因此,不同子进程的消息可能会相互交叉。如何避免此问题?

假设您有三个进程,每个进程都试图输出由四个字符和一个换行符组成的无限系列行:

void four(char c);

int main()
{
    //insert your own error checking
    pid_t p0, p1, p2;
#define PROC(pid,str) pid=fork(); if(0==pid) four(str);
    PROC(p0,'a');
    PROC(p1,'b');
    PROC(p2,'c');

    waitpid(p2, 0,0);
    waitpid(p1, 0,0);
    waitpid(p0, 0,0);

}
如果您的
four
功能为:

void four(char c)
{
    for(;;){
        for(int i=0; i<4;i++)
            putchar(c);
        putchar('\n');
    }
}
你将得到证明你的问题的匹配

解决这个问题最简单的方法是依靠Linux保证,如果
write
参数小于管道缓冲区大小(在我的系统上默认为
4KiB
(您可以从
ulimit
shell内置获取大小),它不会中断针对管道的
write
调用

void-four(字符c)
{
对于(;;){
用于(int i=0;iflock(fd,LOCK_EX))
佩罗尔(“羊群”);

对于(int i=0;i假设您有三个进程,每个进程都试图输出由四个字符和一个换行符组成的无限系列行:

void four(char c);

int main()
{
    //insert your own error checking
    pid_t p0, p1, p2;
#define PROC(pid,str) pid=fork(); if(0==pid) four(str);
    PROC(p0,'a');
    PROC(p1,'b');
    PROC(p2,'c');

    waitpid(p2, 0,0);
    waitpid(p1, 0,0);
    waitpid(p0, 0,0);

}
如果您的
four
功能为:

void four(char c)
{
    for(;;){
        for(int i=0; i<4;i++)
            putchar(c);
        putchar('\n');
    }
}
你将得到证明你的问题的匹配

解决这个问题最简单的方法是依靠Linux保证,如果
write
参数小于管道缓冲区大小(在我的系统上默认为
4KiB
(您可以从
ulimit
shell内置获取大小),它不会中断针对管道的
write
调用

void-four(字符c)
{
对于(;;){
用于(int i=0;iflock(fd,LOCK_EX))
佩罗尔(“羊群”);
对于(int i=0;i所说的“交叉自身”,我想您的意思是担心输出被交错。也就是说,一个进程试图输出“Hello,World!”,而另一个进程打印“再见,芝加哥!”,最终输出是“Hello,Goodby,World!Chicago!”,或类似。解决此问题的最简单方法是确保您编写的每条消息都是使用单个
write
系统调用编写的,并且数据较小。如果您的消息小于1k(大约,确切值取决于系统,通常为4096,很少小于512)。如果使用足够小的缓冲区调用
write
,则写入将是原子的,不会与任何其他进程的输出交错。如果消息的大小与您所在系统的大小不符,则需要使用某种锁定机制。

通过“交叉自身”,我猜您的意思是担心输出被交错。也就是说,一个进程试图输出“Hello,World!”,而另一个进程打印“再见,芝加哥!”,最终输出是“Hello,Goodby,World!Chicago!”,或类似。解决此问题的最简单方法是确保您编写的每条消息都是使用单个
write
系统调用编写的,并且数据较小。如果您的消息小于1k(大约,确切值取决于系统,通常为4096,很少小于512)。如果使用足够小的缓冲区调用
write
,则写入将是原子的,不会与任何其他进程的输出交错。如果消息的大小与您所在系统的大小不符,则需要使用某种锁定机制

  void four(char c)
  {
    int fd;
    fd = open("/proc/self/exe", O_RDONLY); 

    for(;;){
        if(0>flock(fd, LOCK_EX))
           perror("flock");

        for(int i=0; i<4;i++)
            { putchar(c); fflush(stdout); }
        putchar('\n'); fflush(stdout);
        //the pipe buf guarantee won't save us here
        //given all these flushes

        //but this lock will
        if(0>flock(fd, LOCK_UN))
           perror("flock");
   }
}