ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

进程同步的两种实现

2019-04-02 17:51:41  阅读:255  来源: 互联网

标签:两种 parent 进程同步 实现 void pid exit child include


在前文《Linux – 进程控制》博客中,我曾提到过父子进程之间的同步有两种方法:分别是基于管道和信号实现。
为什么需要进程的同步,当我们创建一个新进程时,为了保证父子进程的运行按照我们预期的时序进行,所以需要加入同步机制。下面直接以代码示例来实现两种同步方式。

基于管道实现的进程同步

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "include/debug.h"

static int	pfd1[2], pfd2[2];

void initialize(void)
{
	if (pipe(pfd1) < 0 || pipe(pfd2) < 0)
		err_exit("pipe error");
}

void wake_parent(void)
{
	if (write(pfd2[1], "c", 1) != 1)
		err_exit("write error");
}

void wait_parent(void)
{
	char	c;

	if (read(pfd1[0], &c, 1) != 1)
		err_exit("read error");

	if (c != 'p')
		err_exit("WAIT_PARENT: incorrect data");
}

void wake_child(void)
{
	if (write(pfd1[1], "p", 1) != 1)
		err_exit("write error");
}

void wait_child(void)
{
	char	c;

	if (read(pfd2[0], &c, 1) != 1)
		err_exit("read error");

	if (c != 'c')
		err_exit("WAIT_CHILD: incorrect data");
}


int main (int argc, char *argv[])
{
	pid_t pid;
	int ret;

	initialize();
	if ((pid = fork()) < 0) {
		err_exit("fork() error\n");
	} else if (pid > 0) { //parent
		wait_child();
		pr_info("parent waken up\n");
		pr_info("parent running\n");
		pr_info("wake up child\n");
		wake_child();
		wait(NULL);
	} else {
		pr_info("child running\n");
		pr_info("wake up parent\n");
		wake_parent();
		wait_parent();
		pr_info("child waken up\n");
	}
	return 0;
}

基于信号SIGUSR1和SIGUSR2实现的同步

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <signal.h>
#include "include/debug.h"

static volatile sig_atomic_t sigflag; /* set nonzero by sig handler */
static sigset_t mask, omask, zeromask;

static void sig_usr(int signo)	/* one signal handler for SIGUSR1 and SIGUSR2 */
{
	pr_info("catch signal:%d\n", signo);
	sigflag = 1;
}

void initialize(void)
{
	if (signal(SIGUSR1, sig_usr) == SIG_ERR)
		err_exit("signal(SIGUSR1) error");
	if (signal(SIGUSR2, sig_usr) == SIG_ERR)
		err_exit("signal(SIGUSR2) error");

	sigemptyset(&zeromask);
	sigemptyset(&mask);
	sigaddset(&mask, SIGUSR1);
	sigaddset(&mask, SIGUSR2);

	if (sigprocmask(SIG_BLOCK, &mask, &omask) < 0)
		err_exit("SIG_BLOCK error");
}

void wake_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, &omask, NULL) < 0)
		err_exit("SIG_SETMASK error");
}

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

void wait_child(void)
{
	while (sigflag == 0)
		sigsuspend(&zeromask);
	sigflag = 0;

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

int main (int argc, char *argv[])
{
	pid_t pid;
	int ret;

	initialize();
	if ((pid = fork()) < 0) {
		err_exit("fork() error\n");
	} else if (pid > 0) { //parent
		wait_child();
		pr_info("parent waken up\n");
		pr_info("parent running\n");
		pr_info("wake up child\n");
		wake_child(pid);
		wait(NULL);
	} else {
		pr_info("child running\n");
		pr_info("wake up parent\n");
		wake_parent(getppid());
		wait_parent();
		pr_info("child waken up\n");
	}
	return 0;
}

标签:两种,parent,进程同步,实现,void,pid,exit,child,include
来源: https://blog.csdn.net/rikeyone/article/details/88977157

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有