在LInux下怎么样进行父子进程同步

在LInux下怎么样进行父子进程同步,第1张

/*

* 使用信号实现父子进程之间的同步

*

* TELL_WAIT(): set things up for TELL_xxx &WAIT_xxx

* TELL_PARENT(): tell parent we are done

* WAIT_PARENT(): wait for parent

* TELL_CHILD(): tell child we are done

* WAIT_CHILD(): wait for child

*

* SIGUSR1: the signal parent sends to child

* SIGUSR2: the signal child sends to parent

*/

#include <sys/types.h>

#include <signal.h>

#include <unistd.h>

#include <stdio.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)

}

/* parent goes first program */

int main()

{

pid_t pid

TELL_WAIT()

pid = fork()

if(pid <0) {

printf("fork error\n")

}

else if(pid == 0) {

WAIT_PARENT()

do_task("child task\n")

}

else {

do_task("parent task\n")

TELL_CHILD(pid)

}

return 0

}

/* child goes first program*/

int main()

{

pid_t pid

TELL_WAIT()

pid = fork()

if(pid <0) {

printf("fork error\n")

}

else if(pid == 0) {

do_task("child task\n")

TELL_PARENT(getppid())

}

else {

WAIT_CHILD()

do_task("parent task\n")

}

return 0

}

/*

* 使用管道实现父子进程同步

*

* 父进程在调用TELL_CHILD 时经由上一个管道写一个字符p,子进程在

* 调用TELL_PARENT时,经由下一个管道写一个字符c。相应的WAIT_XXX

* 函数调用read读一个字符,没有读到字符时阻塞(睡眠等待)。

*

*/

static int pfd1[2], pfd[2]

void TELL_WAIT()

{

if(pipe(pfd1) <0 || pipe(pfd2) <0)

printf("pipe error\n")

}

void TELL_PARENT(pid_t pid)

{

if(write(pfd2[1], "c", 1) != 1)

printf("write error\n")

}

void WAIT_PARENT()

{

char c

if(read(pfd1[0], &c, 1) != 1)

printf("read error\n")

if(c != 'p')

printf("WAIT_PARENT: incorrect data\n")

}

void TELL_CHILD(pid_t pid)

{

if(write(pfd1[1], "p", 1) != 1)

printf("write error\n")

}

void WAIT_CHILD()

{

char c

if(read(pfd1[0], &c, 1) != 1)

printf("read error\n")

if(c != 'c')

printf("WAIT_CHILD: incorrect data\n")

}

kill函数用来发送信号给指定的进程,在Shell下输入man 2 kill可获取其函数原型如下:

#include <sys/types.h>

#include <signal.h>

int kill(pid_t pid,int sig)

该函数的行为与第一个参数pid的取值有关,第二个参数sig表示信号编号。

如果pid是正数,则发送信号sig给进程号为pid的进程;

如果pid为0,则发送信号sig给当前进程所属进程组里的所有进程;

如果pid为-1,则把信号sig广播至系统内除1号进程(init进程)和自身以外的所有进程;

如果pid是-1还小的负数,则发送信号sig给属于进程组-pid的所有进程。

如果参数sig是0,则kill()仍执行正常的错误检查,但不发送信号。可以利用这一点来确定某进程是否有权向另外一个进程发送信号。如果向一个并不存在的进程发送空信号,则kill()返回-1,errno则被设置为ESRCH。

函数执行成功返回0,当有错误发生时则返回-1,错误代码存入errno中,详细的错误代码说明请参考man手册。

注意:只有具有root权限的进程才能向其他任一进程发送信号,非root权限的进程只能向属于同一个组或同一个用户的进程发送信号。

更简单的方法是通过进程名给进程发信号。比如你的进程名是 aproc,你自己定义一个信号量18,那么:

#include <signal.h>

#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>

char cmd[256]=""int sig = 18

char procname[]="aproc"

sprintf(cmd, "killall -%d %s\n", sig, procname)

system(cmd)

就能给特定进程发信号了

充分利用system函数,可以简化很多编程工作量,比如查IP地址、查硬盘目录、查磁盘空间等等,编程很麻烦的事都能用system处理,相当于在程序里调用SHELL

#include <stdio.h>

#include <string.h>

#include <unistd.h>

#define BUFSIZE 10

int main(void)

{

char ch,dh,eh

int p[2]//文件描述符

pid_t childpid

if(pipe(p) == -1)//创建管道

{

perror("pipe call")

return -1

}

if((childpid = fork()) == -1)//创建子进程

{

perror("fork call")

return -1

}

if(childpid!=0)//父进程

{

close(p[0])//关闭读文件

do

{

ch = getchar()

write(p[1],&ch,1)//向管道写

}while(ch!='x')//遇到'x'则结束

}

else if(childpid==0)//子进程

{

close(p[1])//关闭写文件

while(1)

{

read(p[0],&dh,1)//从管道读

if(dh == 'x')

{

printf("\n")

return 0

}

else if(dh>='a'&&dh<='z')

{

eh = (char)((int)dh - 32)//转化成大写输出

printf("%c",eh)

}

else {

printf("%c",dh)

}

}

}

}


欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/yw/7619978.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-04-07
下一篇2023-04-07

发表评论

登录后才能评论

评论列表(0条)

    保存