Skip to content

Latest commit

 

History

History
193 lines (146 loc) · 5.5 KB

6.md

File metadata and controls

193 lines (146 loc) · 5.5 KB

进程通信

操作系统提供了一种称为进程通信(IPC)的机制让协作进程之间实现彼此之间的通信。==IPC是利用消息(message),明确地将信息从一个进程地地址拷贝到另一个进程的地址空间,而不适用共享存储器的一种通信机制。==

send和receive原语

在信息通信过程中,接收方和发送方之间有一个协议,是双方都认可其中的信息格式。

在信箱通信中,除了定义信箱结构外,还需要定义原语和接收原语。发送原语和接收原语一般有两种选项,这两个原语都有同步和异步两种语义。

  • send原语:send原语可以是同步或者异步的
  • receive原语可以是阻塞或非阻塞的

一、进程的信号通信系统调用

  1. Signal(sig,function)

功能:允许调用进程控制软中断信号的处理。Sig表示信号,如SIGINT表示按ctrl+c键,SIGQUIT表示按ctrl+\键。

  1. Kill(pid,sig)

功能:向进程号为pid的进程发送信号sig。

二、进程的管道通信系统调用

  1. pipe()系统调用

格式:status=pipe(fd)

int fd[2];

功能:fd用来存放标识管道的两个文件描述符,如果调用成功,fd[0]用于从管道读,fd[1]用于向管道写。如果管道为空,读管道的进程等待;如果管道已满,写管道的进程等待。

  1. close()系统调用

格式:close(fd)

功能:fd为欲关闭文件的文件描述符,用于关闭文件。

  1. read/write系统调用

格式:read(fd,buffer,size)

write(fd,buffer,size)

功能:fd是读/写的文件描述符,buffer是字节指针,存放读/写的字节流的地址,size是要求读/写的字节数。

  1. 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

上述程序中,子进程是否可以在父进程之前执行?为什么?

答:推测要是子程序在父程序之前执行,会进入死锁,程序会一直等待下去。