栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 系统运维 > 运维 > Linux

Linux----进程间通信

Linux 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Linux----进程间通信

进程间通信

1)引入2)管道

Ⅰ匿名管道pipe

①匿名管道特性(MARK一下)②验证匿名管道的特性:同步

总结 ③管道大小 Ⅱ命名管道

①用处②指令mkfifo③函数mkfifo 3)system V IPC

System V 消息队列System V 共享内存System V 信号量 4)POSIX IPC

消息队列共享内存信号量互斥量条件变量读写锁

1)引入

进程间通信可以:

    数据传输:一个进程需要将它的数据发送给另一个进程资源共享:多个进程之间共享同样的资源通知事件:一个进程需要向另一个或一组进程发送消息,通知它(它们)发生了某种事件(如进程终止时要通知父进程)进程控制:有些进程希望完全控制另一个进程的执行(如Debug进程),此时控制进程希望能够拦截另一个进程的所有陷入和异常,并能够及时知道它的状态改变

2)管道 Ⅰ匿名管道pipe

我们用到的 ‘|’ 其实就是匿名管道

#include
int pipe(int pipefd[2]);
#define _GNU_SOURCE
#include
#include
int pipe2(int pipefd[2], int flags);
功能:创建一个管道,一个可用于进程间通信的单向数据通道
解释:

    pipefd[2]: 输出型参数,拿到两个文件描述符数组 pipefd 用于返回引用的两个文件描述符,pipefd[0] 指的是管道的读取端。 pipefd[1] 指的是管道的写端flags:如果 flags 为 0,则 pipe2() 与 pipe() 相同。 可以在标志中对以下值进行按位或运算以获得不同的行为

返回值:

    返回值:成功返回0,失败返回错误代码

下面是一个例子,子进程向父进程传送数据(文件描述符表示)
:为什么要打开(读、写)两个文件?
:1. 只以读/写打开,子进程也只能继承读/写,不能使用管道 2. 为了灵活通信
:为什么父子进程要关闭?
:语义上证明管道的单向特性,防止误操作

①匿名管道特性(MARK一下)

特性:

    管道自带同步机制管道是单向通信的管道是面向字节流(写入数据的量和读出数据的量互不相关)的管道只能保证是具有血缘关系的进程进程通信常用于父子管道可以保证一定程度的数据读取的原子性写入

注意: 进程退出,曾经打开的文件也会被关掉。管道也是文件,管道的生命周期跟随进程

②验证匿名管道的特性:同步

测试代码:

int main()
{
	int pipefd[2]={0};
	if(pipe(pipefd)<0)//创建管道
	{
       perror("pipe");
       return 1;
	}
	pid_t id = fork();
	if(id < 0){
       perror("fork");
       return 1;
	}
	else if(id == 0){ //child
       close(pipefd[0]);
       int count=5;
       const char* msg="The mesage send to parentn";
       while(count){
               write(pipefd[1],msg,strlen(msg));
               sleep(1);
               count--;
       }
       close(pipefd[1]);
       exit(0);
	}
	else{//parent
       close(pipefd[1]);
       char buffer[64];
       while(1){
	        buffer[0]=0;//清空buffer
	        ssize_t size=read(pipefd[0],buffer,sizeof(buffer)-1);//最后一个去了
	        if(size>0){
               buffer[size]=0;//添加
               printf("recieve from child: %s",buffer);
	        }
	        else if(size == 0){
               printf("pipe close,child quitn");
               break;
	        }
	        else
	            break;//TODO
       }
       int status=0;
       if(waitpid(id,&status,0)>0)
       	printf("wait successn");
	}
	return 0;
}


父进程没有设置sleep(1)却每隔1秒才打印
从结果我们可以得出在子进程没有写入的时候,父进程处于等待状态


当我们把写端改为一直写,读端不读,当达到最大写入时会停下来等有空间再进行写入

while(1){
	write(pipefd[1],msg,strlen(msg));
	//sleep(1);
	printf("write:%d",count);
	count++;
}
//father:sleep(100);


可以得出在读端没有读的时候,写端处于等待状态


关闭父进程的读端,同时打印一下退出码(status&0x7f)

else{//parent
	close(pipefd[1]);
	close(pipefd[0]);


写端被OS发送SIGPIPE信号杀死


关闭子进程的写端

else if(id == 0){ //child
	close(pipefd[0]);
	close(pipefd[1]);


父进程的read接收到0,文件结束

总结
写端读端结果
不读写端阻塞
不写读端阻塞
关闭写端被OS发送SIGPIPE信号杀死
关闭父进程的read接收到0,文件结束
③管道大小

使用ulimit -a查看系统资源

验证:
让child每次写入一个字节记录次数

观察到近似65535字节,64KB


两个结果为什么不一样呢?
man 7 pipe可以看到一句话:超过PIPE BUF(4KB)的不具有原子性

4kb的pipe size其实是以原子性写入管道的单元大小


Ⅱ命名管道 ①用处

匿名管道应用的一个限制就是只能在具有共同祖先(具有亲缘关系)的进程间通信,如果我们想在不相关的进程之间交换数据,可以使用FIFO文件来做这项工作,它经常被称为命名管道,命名管道是一种特殊类型的文件

②指令mkfifo

指令mkfifo [文件名],创建一个有名管道

指令测试:

输入重定向到myfifo

③函数mkfifo

#include
#include
int mkfifo(const char *pathname, mode_t mode);
功能:在pathname下创建一个命名管道
解释:

    pathname:路径/文件名mode:(mode & ~umask)是文件的8进制权限,例如0644

返回值:

    成功返回0,失败-1

测试代码:
server.c

int ret=mkfifo("./fifo",0644);
if(ret==-1){
	perror("mkfifo");
	return 1;
}
int fd=open("./fifo",O_RDONLY);
if(fd<0){
	perror("open");
	return 2;
}
char buffer[128];
while(1){
 buffer[0]=0;//清空
 ssize_t size=read(fd,buffer,sizeof(buffer)-1);
 if(size>0){
	  buffer[size]=0;
	  printf("client :> %sn",buffer);
 }
 else if(size==0){
	  printf("client quitn");
	  break;
 }
 else
	  break;
}
close(fd);
return 0;

client.c

int fd=open("./fifo",O_WRONLY);
if(fd<0){
   perror("open");
   return 2;
}
printf("Please Enter:>n");
fflush(stdout);
char buffer[128];
while(1){
	buffer[0]=0;//清空
	ssize_t size=read(0,buffer,sizeof(buffer)-1);//fd==0就是stdin键盘输入
	if(size>0){
	    buffer[size]=0;
	    write(fd,buffer,strlen(buffer));
	}
	else if(size==0){
	    break;
	}
	else
	    break;
}
close(fd);
return 0;

结果:

3)system V IPC System V 消息队列 System V 共享内存 System V 信号量 4)POSIX IPC 消息队列 共享内存 信号量 互斥量 条件变量 读写锁
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/748791.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号