操作系统提供了一种称为进程通信(IPC)的机制让协作进程之间实现彼此之间的通信。==IPC是利用消息(message),明确地将信息从一个进程地地址拷贝到另一个进程的地址空间,而不适用共享存储器的一种通信机制。==
在信息通信过程中,接收方和发送方之间有一个协议,是双方都认可其中的信息格式。
在信箱通信中,除了定义信箱结构外,还需要定义原语和接收原语。发送原语和接收原语一般有两种选项,这两个原语都有同步和异步两种语义。
- send原语:send原语可以是同步或者异步的
- receive原语可以是阻塞或非阻塞的
Signal(sig,function)
功能:允许调用进程控制软中断信号的处理。Sig
表示信号,如SIGINT
表示按ctrl+c键,SIGQUIT
表示按ctrl+\键。
Kill(pid,sig)
功能:向进程号为pid的进程发送信号sig。
pipe()
系统调用
格式:status=pipe(fd)
int fd[2];
功能:fd用来存放标识管道的两个文件描述符,如果调用成功,fd[0]用于从管道读,fd[1]用于向管道写。如果管道为空,读管道的进程等待;如果管道已满,写管道的进程等待。
close()
系统调用
格式:close(fd)
功能:fd为欲关闭文件的文件描述符,用于关闭文件。
read/write
系统调用
格式:read(fd,buffer,size)
write(fd,buffer,size)
功能:fd是读/写的文件描述符,buffer是字节指针,存放读/写的字节流的地址,size是要求读/写的字节数。
Lockf(files,function,size)
功能:用作锁定文件的某些段或整个文件。其中:files是文件描述符,0表示标准输入,1表示标准输出;function是锁定和解锁,1表示锁定,0表示解锁;size是锁定或解锁的字节数,若用0,表示从当前的位置到文件尾。
/*************************************************************************
> File Name: 1.c
> Author: smile
> Mail: 3293172751nss@gmail.com
> Created Time: Thu 26 May 2022 05:33:17 AM PDT
************************************************************************/
#include <stdio.h>
#include <signal.h>
//status=pipe(fd)
void waiting(),stop();
int wait_mark;
main() {
int p1,p2;
while ((p1=fork())==-1); //what空语句号,创建
if (p1>0) { //父进程进入
while ((p2=fork())==-1); //创建一个进程p2
if (p2>0) {
wait_mark=1;
signal(SIGINT,stop); //此时表示中断信号
//1. `Signal(sig,function)`功能:允许调用进程控制软中断信号的处理。`Sig`表示信号,如`SIGINT`表示按ctrl+c键,`SIGQUIT`表示按ctrl+\键。
alarm(1);
signal(SIGALRM,stop);
waiting();
kill(p1,16);
kill(p2,17);
wait(0);
wait(0);
printf("parent process is killed!\n");
exit(0);
} else { //子进程
wait_mark=1;
signal(17,stop); //进程之间进行通信,
waiting();
lockf(1,1,0);
//功能:用作锁定文件的某些段或整个文件。其中:files是文件描述符,0表示标准输入,1表示标准输出;function是锁定和解锁,1表示锁定,0表示解锁;size是锁定或解锁的字节数,若用0,表示从当前的位置到文件尾。
printf("child process 2 is killed by parent!\n");
lockf(1,0,0);
exit(0);
}
} else {
wait_mark=1;
signal(16,stop);
waiting();
lockf(1,1,0);
printf("child process 1 is killed by parent!\n");
lockf(1,0,0);
exit(0);
}
}
void waiting() {
while (wait_mark !=0);
}
void stop() {
wait_mark=0;
}
编译:
root@ubuntu:/c# ./1
child process 2 is killed by parent!
child process 1 is killed by parent!
parent process is killed!
当执行pipe()系统调用时,系统将在内存中建立一个大小为10kb的无名管道文件,当执行fork()调用时,父子进程共享管道文件,父子进程都有两个文件描述符与管道文件对应。以下程序是父子进程通过管道进行通信。
#include <stdio.h>
#define MSGSIZE 16
char *msg1="hello,#1";
char *msg2="hello,#2";
char *msg3="hello,#3";
main() {
char inbuf[MSGSIZE]; //定义一个数组,
int p[2],j,pid;
if(pipe(p)<0) {
//status=pipe(fd)
//fd用来存放标识管道的两个文件描述符,如果调用成功,fd[0]用于从管道读,fd[1]用于向管道写。如果管道为空,读管道的进程等待;如果管道已满,写管道的进程等待。
perror("pipe call err");
exit(1); //结束
}
if((pid=fork())<0) { //fock() 2**2 不走返回err
perror("fork call err");
exit(2);
}
if (pid>0) { //父进程走分支
close(p[0]);
/*关闭父进程读*/
write(p[1],msg1,MSGSIZE); //写入管道
write(p[1],msg2,MSGSIZE);
write(p[1],msg3,MSGSIZE);
wait(0); //等待
}
if(pid==0) { //子进程走分支
close(p[1]);
/*关闭子进程写*/
for (j=0;j<3;j++) {
read(p[0],inbuf,MSGSIZE);
printf("------in child--------%s\n",inbuf);
}
exit(0);
}
exit(0);
}
编译:
root@ubuntu:/c# ./2
------in child--------hello,#1
------in child--------hello,#2
------in child--------hello,#3
上述程序中,子进程是否可以在父进程之前执行?为什么?
答:推测要是子程序在父程序之前执行,会进入死锁,程序会一直等待下去。