进程通信
1、进程建通信概述
1、目的:
为何需要进程间通信?
1、数据传输
一个进程需要将他的数据发送给另外一个进程。
2、资源共享
多个进程之间共享同样的资源。
3、通知事件
一个进程需要向一个或一组进程发送消息,通知它发生了某种事件。
4、进程控制
有些进程希望完全控制另一程序的执行(如Debug进程),此时控制进程希望能够拦截另一个进程的所有操作,并能够及时知道他的状态改变。
2、来源:
linux进程间通信(IPC)是由以下几部分发展而来:
1、UNIX进程间通信;
2、基于system V进程间通信;
3、POSIX进程间通信;
注意:
posix是可移植操作系统接口;
3、进程间通讯方式包括:
1、管道(pipe)和有名管道(FIFO)
2、信号(signal)
3、消息队列
4、共享内存
5、信号量
6、套接字(socket)
2、管道通讯
特点:先进先出,尾进头出;
1、管道创建:
管道包括无名管道和有名管道两种:
无名管道:用于父进程和子进程之间的通信;
有名管道:用于同一系统之间任意两个进程;
1、无名管道:
(1)通过 pipe() 函数创建无名管道:
int pipe(int filedis[2]);
当一个管道创建之后,会建立两个文件描述符:
filedis[0]:用于读管道;
filedis[1]:用于写管道;
实例 1:
创建一个管道;
#include<unistd.h>
#include<errno.h>
#include<stdio.h>
#include<stdlib.h>
int main()
{
int pipe_fd[2];//定义两个int类型的文件描述符;
printf("fd[0]=%d,fd[1]=%d\n",pipe_fd[0],pipe_fd[1]);
//未创建管道符之前,
if(pipe(pipe_fd)<0)
{
printf("pipe create error\n");
return -1;
}
else
{
//创建管道符之后,管道描述符的数值;
printf("fd[0]=%d,fd[1]=%d\n",pipe_fd[0],pipe_fd[1]);
printf("pipe create success\n");
}
close(pipe_fd[0]);
close(pipe_fd[1]);
}
注意:
必须在系统调用fork()之前先调用pipe(),否则子进程将无法继承文件的描述符。
即:先铺管道,才有进程。
否则的话会创建两个管道:父进程一个,子进程一个,个用个的。
实例 2:
#include<stdio.h>
#include<sys/types.h>
#include<errno.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
int main()
{
int pipe_fd[2];
pid_t pid;
char buf_r[100];
char * p_wbuf;
int r_num;
memset(buf_r,0,sizeof(buf_r));
//创建管道;
if(pipe(pipe_fd)<0)
{
printf("pip create error\n");
return -1;
}
//创建子进程;
if((pid=fork())==0) //子进程执行序列
{
printf("\n");
close(pipe_fd[1]);//子进程先关闭了管道的写端
sleep(2);//为何睡眠?/*让父进程先运行,这样父进程先写子进程才有内容读*/
if ((r_num=read(pipe_fd[0],buf_r,100))>0)
{
printf("%d numbers read from the pipe is %s\n",r_num,buf_r);
}
close(pipe_fd[0]);
exit(0);
}
else if(pid>0)//父进程执行序列
{
close(pipe_fd[0]); //父进程先关闭了管道的读端
if (write(pipe_fd[1],"hello",5)!=-1)
printf("parent write hello! \n");
if(write(pipe_fd[1],"pipe",5)!=-1)
printf("parent write pipe! \n");
close(pipe_fd[1]);
waitpid(pid,NULL,0); /*等待子进程结束*/
exit(0);
}
return 0;
}
结果显示:
parent write hello!
parent write pipe!
(sleep 2 )
10 numbers read from the pipe is hellopipe
代码分析:
read()函数的原型是
int read(int fd,void *buf,int count);
解释:
char buff[1024];
int fd1,i;
read(fd1,buff,sizeof(buff))
参数依次为:文件描述符,变量,读取长度
功能是“从文件说明符fd相关联的文件中读取count个字符,并把这些字符存储到buf所指的缓冲区回中。
返回值是操作成功时所读到的字节数,在文件结束时可能少于count个字答节;若返回值为-1则说明出错了,返回0则表示到达文件尾端。
2、命名管道
定义:
#include<sys/types.h>
#include<sys/stat.h>
int mkfifo(const char * pathname,mode_t mode);
参数:
pathname: FIFO文件名;
mode: 属性(见文件操作章节)
一旦创建一个FIFO就可以通过open打开他,一般的文件访问函数(close,read,write等)都可以用于FIFO。
3、信号通讯
4、共享内存