码迷,mamicode.com
首页 > 系统相关 > 详细

linux c编程:进程控制(二)_竞争条件

时间:2018-05-14 23:02:29      阅读:251      评论:0      收藏:0      [点我收藏+]

标签:r++   使用   条件   处理   标准   9.png   共享数据   atom   font   

 

前面介绍了父子进程,如果当多个进程企图对共享数据进行处理。而最后的结果又取决于进程运行的顺序时,就认为发生了竞争关系。通过下面的例子来看下

在这里标准输出被设置为不带缓冲的,于是父子进程每输出一个字符就要进行一次write调用。这样做的目的是尽可能多次地在两个进程之间进行切换,以便演示竞争条件。

static void charatatime(char *str){

    char *ptr;

    int c;

    setbuf(stdout,NULL);

    for(ptr=str;(c=*ptr++)!=’\0‘;)

        putc(c,stdout);

}

void competition(){

    pid_t pid;

    if ((pid=fork()) < 0){

        printf("error");

    }

    else if(pid == 0){

        charatatime("output from child\n");

    }

    else{

        charatatime("output from parent\n");

    }

    exit(0);

}

来看下系统运行的结果:

第一次:

技术分享图片

第二次:

技术分享图片

第三次:

技术分享图片

通过三次运行结果来看,除了第一次运行正常外,其他两次的字符都是杂乱的。原因就在于父子进程启动的顺序是有先有后的。

为了避免竞争条件,在多个进程之间需要有某种形式的信号发送和接收的方式。在linux中可以使用信号机制。具体实现方法如下

#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>

#include <sys/wait.h>

#include <fcntl.h>

#include <signal.h>

#include <sys/types.h>

 

static volatile sig_atomic_t sigflag;

static sigset_t newmask, oldmask, zeromask;

/* signal handler for SIGUSR1 and SIGUSR2 */

static void sig_usr(int signo)

{

 sigflag = 1;

 return;

}

void TELL_WAIT()

{

 if(signal(SIGUSR1, sig_usr) == SIG_ERR)

  printf("signal SIGUSR1 error\n");

 if(signal(SIGUSR2, sig_usr) == SIG_ERR)

  printf("signal SIGUSR2 error\n");

 

 sigemptyset(&zeromask);

 

 sigemptyset(&newmask);

 sigaddset(&newmask, SIGUSR1);

 sigaddset(&newmask, SIGUSR2);

 

 /* block SIGUSR1 and SIGUSR2, and save current signal mask */

 if(sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0)

  printf("SIG_BLOCK error\n");

}

void TELL_PARENT(pid_t pid)

{

 kill(pid, SIGUSR2); /* tell parent we are done */

}

void WAIT_PARENT()

{

 while(sigflag == 0)

  sigsuspend(&zeromask); /* wait for parent */

 

 sigflag = 0;

 

 /* reset signal mask */

 if(sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)

  printf("SIG_SETMASK error\n");

}

void TELL_CHILD(pid_t pid)

{

 kill(pid, SIGUSR1);

}

void WAIT_CHILD()

{

 while(sigflag == 0)

  sigsuspend(&zeromask); /* wait for parent */

 

 sigflag = 0;

 

 /* reset signal mask */

 if(sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)

  printf("SIG_SETMASK error\n");

}

void do_task(char *task_str)

{

 printf("%s\n", task_str);

}

那么在之前的代码更新如下:

oid competition(){

    pid_t pid;

    TELL_WAIT();

    if ((pid=fork()) < 0){

        printf("error");

    }

    else if(pid == 0){

        WAIT_PARENT();  //等待父进程先进行

        charatatime("output from child\n");

    }

    else{

        charatatime("output from parent\n");

        TELL_CHILD(pid); //告诉子进程运行

    }

    exit(0);

}

此时运行的顺序就会固定。也不会出现杂乱的字符。

技术分享图片

 

linux c编程:进程控制(二)_竞争条件

标签:r++   使用   条件   处理   标准   9.png   共享数据   atom   font   

原文地址:https://www.cnblogs.com/zhanghongfeng/p/9038387.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!