linux进程间同步

xiejimywei 2012-04-24 10:14:04
在stevens大师的书中看到如下代码:
#include "apue.h"

static void charatatime(char *);

int main()
{
pid_t pid;

TELL_WAIT();

if((pid = fork()) < 0)
{
err_sys("fork error");
}
else if(pid == 0)
{
WAIT_PARENT();
charatatime("output from child\n");
}
else
{
charatatime("output from parent\n");
TELL_CHILD(pid);
}
exit(0);
}

static void charatatime(char *str)
{
char *ptr;
int c;
setbuf(stdout, NULL);
for(ptr = str; (c = *ptr++) != 0;)
putc(c, stdout);
}
其中TELL_WAIT、WAIT_PARENT、TELL_CHILD在另外一个文件tellwait.c中,被编译成lib文件,如下:
#include "apue.h"

static volatile sig_atomic_t sigflag; /* set nonzero by sig handler */
static sigset_t newmask, oldmask, zeromask;

static void
sig_usr(int signo) /* one signal handler for SIGUSR1 and SIGUSR2 */
{
sigflag = 1;
}

void
TELL_WAIT(void)
{
if (signal(SIGUSR1, sig_usr) == SIG_ERR)
err_sys("signal(SIGUSR1) error");
if (signal(SIGUSR2, sig_usr) == SIG_ERR)
err_sys("signal(SIGUSR2) error");
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)
err_sys("SIG_BLOCK error");
}

void
TELL_PARENT(pid_t pid)
{
kill(pid, SIGUSR2); /* tell parent we're done */
}

void
WAIT_PARENT(void)
{
while (sigflag == 0)
sigsuspend(&zeromask); /* and wait for parent */
sigflag = 0;

/*
* Reset signal mask to original value.
*/
if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)
err_sys("SIG_SETMASK error");
}

void
TELL_CHILD(pid_t pid)
{
kill(pid, SIGUSR1); /* tell child we're done */
}

void
WAIT_CHILD(void)
{
while (sigflag == 0)
sigsuspend(&zeromask); /* and wait for child */
sigflag = 0;

/*
* Reset signal mask to original value.
*/
if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)
err_sys("SIG_SETMASK error");
}
我想问的是,tellwait.c中的sigflag是父子进程共享的吗?链接库难道父子进程共享吗?链接库不是采用写时复制机制吗?求高手指点迷津啊。。。。
...全文
286 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
qq120848369 2012-04-26
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 的回复:]

恩,ls说的对,信号控制同步,
另外,有个地方一直疑惑:
第一次运行到 if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0) 之前,
就来了信号的话,是不是 进程就会默认处理了?比如退出?
[/Quote]

父进程必须做sigprocmask阻塞信号之后再创建子进程,否则父进程kill信号和子进程挂起等待信号的时序无法保证:子进程还没有进入sigsuspend,父进程就kill信号了,那么子进程信号处理函数调用完成后进入sigsuspend,将永远死住,除非父进程再kill一次信号。 当然这里问题不大,因为while()判断了,但是这里又涉及到一个变量检查的线程安全性问题,只有类似于pthread_mutex_lock或者sigprocmask阻塞信号的调用才能保证在检测变量时不被其他线程修改,保证线程安全性。
smallbear_2008 2012-04-25
  • 打赏
  • 举报
回复
恩,ls说的对,信号控制同步,
另外,有个地方一直疑惑:
第一次运行到 if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0) 之前,
就来了信号的话,是不是 进程就会默认处理了?比如退出?
xiejimywei 2012-04-25
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 的回复:]
sigflag是各自都有的吧,父子进程修改某变量时,就不再是共享了,
这个lib是静态的?编译时会复制进去的、动态库也没关系吧,因为sigflag和信号集等应该都有一份了

个人意见,等大侠哦
[/Quote]
如果不共享的话,怎么实现同步呢,代码当中是根据sigflag的值进行同步的啊。。。
qq120848369 2012-04-25
  • 打赏
  • 举报
回复
信号啊,共享个屁啊。

父进程kill信号给子进程,子进程信号函数标记变量,sigsuspend被唤醒检查变量满足,于是子进程开始执行。

父进程在kill信号之后开始等待子进程给它kill信号,同样是sigprocmask +sigsuspend的等待,子进程kill信号给父进程,父进程sigsuspend被唤醒检查变量被设置于是程序结束。

这个编程方法和条件变量+互斥量是完全一样的:

pthread_mutex_lock == sigprocmask
pthread_cond_wait == sigsuspend
pthread_cond_signal == kill
pthread_mutex_unlock == sigprocmask

加锁/阻塞信号 是为了在检查变量时是线程安全的, 而sigsuspend/cond_wait是保证解锁/解信号阻塞与挂起等待是原子的, 这样才能保证不漏掉信号/条件的唤醒.

smallbear_2008 2012-04-24
  • 打赏
  • 举报
回复
sigflag是各自都有的吧,父子进程修改某变量时,就不再是共享了,
这个lib是静态的?编译时会复制进去的、动态库也没关系吧,因为sigflag和信号集等应该都有一份了

个人意见,等大侠哦

23,120

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 应用程序开发区
社区管理员
  • 应用程序开发区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧