进程间通信

进程间通信

无名管道(pipe)

无名管道只能继承,在进程中创建管道,一个进程写数据,一个进程读数据。

1、特点

(1)只能用于有亲缘关系的的进程间通信(无实际文件与其对应);
(2)单工通信模式,具有固定的读端和写端。

2、无名管道创建 - pipe

#include<unistd,h>
int pipe(int pfd[2]);
返回值:成功返回0,失败返回EOF
参数:pfd包括两个元素的整形数组,用来保存文件描述符,pfd[0]用于读管道,pfd[1]用于写管道。

例示 - 无名管道
子进程1和子进程2分别往管道中写入字符串,父进程读管道内容并打印。

#include<stdio.h.>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
int main(void){
	pid_t pid1, pid2;
	char buf[32];	//缓冲区
	int pfd[2];
	//先创建管道,在创建子进程
	if(pipe(pfd) < 0){	
		perrpr("pipe");
		exit(-1);
	}
	if((pid1 == fork()) < 0){
		perror("fork");
		exit(-1);
	}else if(pid1 == 0){	//子进程1
		strcpy(buf, I'm process1\n");
		write(pfd[1], buf, 32);
		exit(0);
	}else{	
		if((pid2 == fork()) < 0){
			perror("fork");
			exit(-1);
		}else if(pid2 == 0){	//子进程2
			strcpy(buf, I'm process1\n");
			write(pfd[1], buf, 32);
			exit(0);
		}else{
			wait(NULL);//父进程
			read(pfd[0], buf, 32);
			printf("%s\n", buf);
			wait(NULL);
			read(pfd[0], buf, 32);
			printf("%s\n", buf);
		}
	}
	return 0;
}

3、读无名管道

(1)写端存在
至少有一个进程可以通过文件描述符写管道
1)有数据,read返回实际读取的字节数;
2)无数据,进程读阻塞。
(2)写端不存在
1)有数据,read返回都取自结束;
2)无数据,read返回0。

4、写管道

(1)读端存在
1)有足够空间
write返回实际写入的字节数
2)无足够空间/空间不足
原子操作,有多少写多少,阻塞到有空间写完

**如何获取无法管道大小?**
1)循环写入管道,知道阻塞;
2)统计循环次数。
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
int main(){
	int cout = 0, pfd[2];
	char buf[1024];
	if(pipe(pfd) < 0){
		perror("pipe\n");
		exit(-1);
	}
	while(1){
		printf("wrote %d kbyte \n", ++cout);
	}
	return 0;
}

(2)无读端
管道断裂!!!

如何验证管道断裂(进程被信号结束)
1)子进程写管道
2)父进程回收
.....
int main(){
	pid_t pid;
	int pfd[2];
	char buf[32];
	if(pipe(pfd) < 0){
		perror("pipe");
		exit(-1);
	}
	close(pfd[0]);	//读端关闭
	if((pid == fork()) < 0){
		perror("fork");
		exit(-1);
	}else if(pid == 0){		//子进程	
		write(pfd[1], buf, 32);
		exit(0);
	}else{
		wait(&status);
		printf("status = %x\n", status);
	}
	return 0;
}

有名管道(fifo)

1、特点

(1)有一个实际文件(有名称,有路径)
(2)打开时可指定读写方式
(3)通过文件IO操作,内容存在内存中(读端写端都关闭时,管道内容被释放)

2、有名管道创建 - mkfifo

#include<unistd.h>
#include<fcntl.h>
int mkfifo(const char *path, mode_t mode);
返回值:成功返回0,失败返回EOF
参数:path创建的管道文件路径(如果没指明,只在当前目录下)
	 mode管道文件的权限,如0666

3、有名管道读写 - 示例

进程A:循环从键盘输入并写入有名管道mkfifo,输入quit时退出,
进程B:循环统计A每次写入字符串长度。

信号(signal)

1、特点

  • 信号机制 - 内核产生的一种通信机制,是在软件层次上对中断机制的一种模拟,是一种异步通信。
    补充:中断:外部设备需要被处理时,产生一个中断信号,cpu收到中断信号后,在执行当前指令响应处理中断,cpu返回继续执行指令。
    -Linux内核通过信号通知用户进程,不同的信号类型代表不同的事件。kill -l显示当前系统中所有支持的信号类型
    -进程对信号有不同的响应方式
    1)缺省方式:系统对每个信号都有缺省方式;
    2)忽略信号:进程收到信号后不做处理;
    3)捕捉信号(注册信号):设定信号处理函数,进程收到后,自动处理。
常用信号默认操作
SIGHUP关闭终端时产生,通常发给所有相关进程终止
SIGINT再键入INIR(crtl -c)时产生,发送给前台进程终止
SIGQUIT与SIGINT类似,由QUIT产生终止
SIGILL遇到非法指令终止
SIGSEV(段错误)非法访问内核(野指针 空指针 数组越界终止
SIGPIPE当进程往一个没有读端管道写入时产生代表管道断裂终止
SIGKILL(高级别,不能设置)用来结束进程终止
SIGSTOP(高级别)暂停进程暂停进程
SIGSTPctrl-z发出暂停进程
SIGCONT信号让进程进入运行太=态继续运行
SIGALRM用于通知进程定时器时间已到终止
SIGUSR1/2保留用户程序使用终止

2、信号相关命令

(1)kill [-signal] pid 向一个进程发信号(进程号,进程组号)

  • sig 默认发送 -15 终止进程
  • pid 指定发送对象
    kill -9 -1 发送给所有进程(结束)
    kill -9 6437 发送给6437进程
    -9 8126 向租号8126的进程组发送

(2)killall [-u user |prog] 会检查权限,防止结束别人进程

  • prog 制定进程名
  • user 指定用户名
    killall a.out 默认发送15
    killall -u linux

(3)信号发送 - kill/raise, alarm/pause

#include<unistd.h>
#include<signal.h>
int kill(pid_t pid,int sig);
int raise(int sig);
返回值:成功返回0,失败返回EOF;
参数pid接受进程的进程号,0代表同组进程,-1代表所有进程。
	sig信号类型
int alarm(unsigned int seconds);//定时器
成功返回上个定时器的剩余时间,失败返回EOF,Linux系统只有一个定时器
参数:second定时器的时间,单位秒
int pause(void);
进程一直阻塞,直到被信号打断
返回值:被信号中断返回-1,errno为EINTR
#include <stdio.h>
#include<stdlib.h>
#include<unistd.h>

int main(){
	alarm(3);		//指定3秒后闹钟时间到
	pause();		//睡眠
	printf("I have been wake up\n");
	return 0;
}

(4)设置信号响应方式 - signal

#include<unistd.h>
#include<signal.h>
void (*signal(int signo, void (* handler)(int)))(int);
参数:signo要设置的信号类型
     第二个函数指针:存放某个函数入口地址,选定义一个信号处理函数
返回值:成功返回原先的信号处理函数,失败返回SIG_ERR
例
void handler(int signo){
 	if(signo == SIGINT){
 		printf("I habe got SIGINT!\n");
 	}else if(signo == SIGQUIT	){
 		printf("i HAVE GOT SIGQUIR\N")
 	}
 }
 int main(){
 	signal(SIGINT,handler);
 	signal(SIGQUIT, handler);
 	while(1)
 		pause();
 	return 0;
 }

共享内存(share memory)

消息队列(messege queue)

信号灯集(semaphore set)

域套接字(socket)

  • 9
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值