Linux-IPC进程间通信

1.1 信号

信号产生的情况

                1. 键盘事件    ctrl + C发出中断信号    
                2. 软件层面    在程序中调用kill函数发送信号
                3. 硬件问题    外设出错或者其他原因收到的信号
                4. 内存管理错误    

信号的处理方式有三种:

                默认:执行信号默认的动作

                忽略:忽略信号

                捕捉:捕捉信号去执行自定义的动作

可以使用 kill -l 查看当前系统所有信号。

函数原型

 typedef void (*sighandler_t)(int);            //声明函数指针类型

 sighandler_t signal(int signum, sighandler_t handler);

功能:处理信号(默认、捕捉、忽略)
参数:
        signum:     要处理的信号
        handler:    要对信号进行的处理动作
        SIG_IGN: 忽略
        SIG_DFL: 执行默认动作,要么填为信号处理函数
返回值:成功返回信号处理函数的前一个值  失败error

#include <signal.h>
#include <stdio.h>
#include <unistd.h>

/* 信号处理函数 */
void signal_handle(int signum){
	if(signum == 2){
		printf("catch 2 signal..\n");
	}
}
int main(){
	//默认--对2号信号执行默认动作
	//signal(SIGINT, SIG_DFL);

	//捕捉--捕捉到2号信号打印字符串
	signal(SIGINT, signal_handle);//会将第一个参数传递给信号处理函数

	//signal(2, SIG_IGN);//忽略

	while(1);
	return 0;
}

1.2 无名管道

        借助于内核完成,会在内核创建一根管道,使用函数pipe创建并拿到管道的两端(读端和写端),两端以数组的成员形式存在,分别是两端的文件描述符,对文件描述符操作相当于对管道的读端和写端操作。并且无名管道只能在亲缘进程间通信,管道的大小为64K,如果管道满,再写会阻塞

函数原型:

int pipe(int pipefd[2]);

                功能:创建无名管道
                参数:    
                    pipefd:      数组,存放管道两端的文件描述符
                    pipefd[0]: 读端
                    pipefd[1]: 写端

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>

#include <sys/types.h>
#include <sys/wait.h>
int main(){
	//创建无名管道
	int pipefd[2];
	if(-1 == pipe(pipefd)){
		perror("pipe");
		exit(EXIT_FAILURE);
	}

	pid_t cpid;
	//创建进程
	if(-1 == (cpid = fork())){
		perror("fork");
		exit(EXIT_FAILURE);
	}	

	if(cpid == 0){		//子进程-写操作
		char cbuffer[10] = {0};
		while(1){
			memset(cbuffer, 0, sizeof(cbuffer));
			printf("input > ");
			fgets(cbuffer, sizeof(cbuffer), stdin);
			cbuffer[strlen(cbuffer)-1] = '\0';
			write(pipefd[1], cbuffer, strlen(cbuffer));
		
			if( strncmp("quit", cbuffer, 4) == 0)
				break;
		}
		exit(EXIT_SUCCESS);
	}else{				//父进程
		char pbuffer[10] = {0};
		while(1){
			memset(pbuffer, 0, sizeof(pbuffer));
			read(pipefd[0], pbuffer, sizeof(pbuffer));
			printf("data = %s\n", pbuffer);

			if( strncmp("quit", pbuffer, 4) == 0)
				break;
		}
		wait(NULL);
		exit(EXIT_SUCCESS);
	}
	
	return 0;
}

无名管道读写规则

        1.写端和读端存在,读管道,有多少读多少,管道为空,读阻塞
        2.写端和读端存在,写管道,有多少写多少,管道为满,写阻塞
        3. 读端不存在,写管道,管道破裂,会发出信号SIGPIPE
        4.写端不存在,读管道,有多少读多少,管道为空直接返回

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>

void signalHandle(int signum){
	printf("管道破裂\n");
}

int main(){
	//创建无名管道
	int pipefd[2];
	if(-1 == pipe(pipefd)){
		perror("pipe");
		exit(EXIT_FAILURE);
	}

	//在管道破裂之前就执行捕捉信号的动作
	signal(SIGPIPE, signalHandle);

	//关闭读端,写操作
	close(pipefd[0]);

	write(pipefd[1], "hello", 5);
	
	return 0;
}

1.3 有名管道

        有名管道可以使用在任意进程间通信,因为有名管道直接创建FIFO类型的管道文件,可供系统中的任意一个进程访问。

函数原型:  

int mkfifo(const char *pathname, mode_t mode);

        功能:创建有名管道文件
        参数
                    pathname: 有名管道文件的路径以及名称
                    mode    : 创建管道文件时的权限
        返回值:成功0 失败-1

创建管道文件:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>

int main(){
	//创建管道文件
	//创建在Linux操作系统的任意一个能访问到的目录下
	//不能创建在共享文件夹中,windows不支持管道文件类型
	if(-1 == mkfifo("/home/linux/File_fifo", 0666)){
		perror("mkfifo");return -1;
	}

	getchar();//清除多余字符

	system("rm /home/linux/File_fifo -rf");

	return 0;
}

写:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <fcntl.h>


int main(){
	//打开管道文件
	int fd;
	if(-1 == (fd = open("/home/linux/File_fifo", O_RDWR))){
		perror("open");return -1;
	}

	char buffer[10] = {0};
	while(1){
		memset(buffer, 0, sizeof(buffer));
		printf("input > ");
		fgets(buffer, sizeof(buffer), stdin);
		buffer[strlen(buffer)-1] = '\0';
		write(fd, buffer, strlen(buffer));
	
		if( strncmp("quit", buffer, 4) == 0)
			break;
	}
	
	return 0;
}

读:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <fcntl.h>

int main(){
	//打开管道文件
	int fd;
	if(-1 == (fd = open("/home/linux/File_fifo", O_RDWR))){
		perror("open");return -1;
	}

	char buffer[10] = {0};
	while(1){
		memset(buffer, 0, sizeof(buffer));
		
		read(fd, buffer, sizeof(buffer));
		printf("data = %s\n", buffer);
	
		if( strncmp("quit", buffer, 4) == 0)
			break;
	}
	
	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值