进程通信(同一主机)

1.概述

进程通信机制包括:

传统的UNIX进程间通信:无名管道、有名管道、信号

System V 进程间通信:消息队列、信号量、共享内存

2.管道通信

在这里插入图片描述

2.1无名管道

1.特点

(1)适用具有亲缘关系的进程

(2)是特殊的文件,read(),write()

(3)但不在文件系统中,存在内核中

(4)半双工在这里插入图片描述

2.无名管道的创建与关闭

创建:

int pipe_pid[2];
if ( pipe(pipe_fd) < 0 ){
	perror("fail to pipe");
	exit(-1);
}

关闭:

close(pipe_fd[0])

3.注意点

(1)管道读端存在时,写入数据才有意义,否则Broken Pipe。
(2)不保证写入的原子性。
(3)父子进程先后次序不保证。

4.代码示例

首先创建管道,而后父进程用fork()创建子进程,最后关闭父进程的写端,关闭子进程的读端,建立管道通信。

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

int main ( void ){
	int pipe_fd[2];
	if ( pipe(pipe_fd) < 0 )//创建管道
	{
		perror("piep errpr");
		exit(-1);
	}

	//创建子进程
	pid_t pid = fork();
	
	//判错
	if ( pid < 0 ){
		perror("fork error");
		exit(-1);
	}
	//子进程发送信息
	else if (0 == pid){
		//1.关闭读端
		close(pipe_fd[0])//2.写入数据
		char buf[20] = {0};
		printf("子进程发送数据:");
		fgets( buf, sizeof(buf), stdin);
		//写入管道
		write( pipe_fd[1], buf, strlen(buf) );
		//3.关闭写端
		close( pipe_fd[1] );
	}
	//父进程接受消息
	else if( pid > 0 ){
		//1.关闭写端
		close ( pipe_fd[1] );
		//2.读取数据
		buf[20] = {0};
		printf("父进程接收数据:");
		read ( pipe_fd[0], buf, strlen(buf) );
		//3.关闭读端
		close ( pipe_fd[0] );

		//收集子进程退出信息
		waitpid ( pid, NULL, 0 );
		exit(0);
	}
}

2.2有名管道

1.特点

(1)适用于互不相关的进程

(2)是文件系统中的文件open write read close,先进先出FIFO

(3)不支持lseek()函数

`lseek()` 是一个系统调用函数。
功能:改变文件读写位置、移动文件指针到文件的任意位置、
     以及判断文件指针的位置等。
参数:文件描述符、移动的偏移量和移动的起始位置。
返回值:移动后的文件指针位置,出错 -1

2.创建有名管道

#include <fcntl.h>
#include <sys/types.h>

//mkfifo( 文件名, 文件权限 );成功0,失败-1.
if ( mkfifo(newfifo, 0664) < 0 ){
	perror("fail to mkfifo");
	exit(-1);
}

3.有名管道FIFO出错信息

EACCESS:指定路径无可执行权限
EEXIST:指定文件已存在
ENAMETOOLONG:路径名称太长
ENOENT:文件不存在
ENOSPC:空间不足
ENOTDIR:目录存在却非真正的目录
EROFS:指定文件存在于只读文件系统内

4.代码示例

写管道程序:

//fifo_write.c
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>

#define MYFIFO "myfifo"

int main( int argc, char* argv[])
{
	int fd;
	int nwrite;
	
	if (argc < 2){
		printf("运行时输入字符串\n");
		exit(-1);
	}

	//以只写方式打开有名管道
	fd = open(MYFIFO, O_WRONLY)
	if(fd < 0)
	{
		perror("fail to open fifo");
		exit(-1);
	}
	//向管道中写入字符串
	nwrite = write(fd, argv[1], strlen(argv[1]+1) );
	if ( nwrite > 0 ){
		printf("向FIFO中写入%s\n", argv[1]);
	}
	close(fd);

	return 0;
}

读管道程序:

//fifo_read.c
//头文件同上
int main()
{
	char[256];
	int fd;

	//判断FIFO是否存在
	if(access(MYFIFO, F_OK) == -1){  //FIFO不存在
		if(mkfifo(MYFIFO, 0664) < 0){
			perror("fail to open fifo");
			exit(-1);
		}
	}
	
	//以只读方式打开有名管道
	fd = open(MYFIFO, O_RDONLY)
	if(fd < 0 ){
		perror("fail to open file");
		exit(-1);
	}

	while(1){
		memset(buf, 0, sizeof(buf) );		
		nread = read(fd, buf, 256);
		if(nread > 0){
			printf("从管道中读取的内容为:%s\n", buf);
		}
	}
		close(fd);
		
		return 0;
	}

首先运行读管道程序,若管道中无数据,就一直阻塞到写入数据

3.信号通信

3.1 64种信号

3.2 信号产生

-硬件产生

ctrl + c
ctrl +
ctrl +

-软件产生

raise()函数
kill()函数

-内核产生

alarm()定时器
pause()调用进程挂起,直到收到信号为止

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值