Linux系统进程通信的主要方式是什么,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。
进程间通信常见方式如下:
管道
FIFO
消息队列
信号量
共享内存
UNXI域套接字
套接字(Socket)
管道是一种古老的IPC通信形式。它有两个特点:
半双工,即不能同时在两个方向上传输数据。有的系统可能支持全双工。
只能在父子进程间。经典的形式就是管道由父进程创建,进程fork子进程之后,就可以在父子进程之间使用了。
使用popen函数和pclose函数结合来执行系统命令,就用到了管道,它们声明如下:
FILE *popen(const char *command,const char *type); int pclose(FILE *stream);
system()函数虽然也能够执行系统命令,但是无法获取执行状态码,而执行系统命令本质上就需要创建子进程来完成,因此利用管道可以很方便的获取子进程的输出内容。本文不详细展开。
我们看一个简单的使用管道的例子,这里使用了pipe函数来创建管道:
#include #include #include #define MAX_LEN 128 int main(void) { /*0为读,1为写*/ int fd[2] = {0}; //描述符 pid_t pid = 0; char line[MAX_LEN] = {0}; int n = 0; /*创建管道,需要传入两个文件描述符*/ if(pipe(fd) 0) { /*关闭管道的写描述符*/ close(fd[1]); /*从管道读取数据*/ n = read(fd[0],line,MAX_LEN); printf("read %d bytes from pipe :%s\n",n,line); } /*子进程*/ else { /*关闭管道的读描述符*/ close(fd[0]); /*向管道写入数据*/ write(fd[1],"www.yanbinghu.com",sizeof("www.yanbinghu.com")); } return 0; }
在程序中,我们创建了一个管道,父进程关闭了写通道,子进程关闭读通道;子进程向管道内写入字符串,而父进程从管道中读取字符串并输出。
运行结果:
read 18 bytes from pipe :www.yanbinghu.com
FIFO也被称为命名管道,与管道不同的是,不相关的进程也能够进行数据交换。
涉及FIFO操作主要函数为:
int mkfifo(const char *path, mode_t mode);
而FIFO也常常有以下两个用途:
无需创建中间临时文件,复制输出流
多客户-服务进程应用中,通过FIFO作为汇聚点,传输客户进程和服务进程之间的数据
我们看一个简单的例子,写进程代码如下:
#include #include #include #include #include #include #define FIFO "/tmp/fifo" #define MAX_LEN 128 int main(void) { int writeFd; char line[MAX_LEN] = {0}; if(mkfifo(FIFO,S_IRUSR|S_IWUSR)它首先创建了一个FIFO,并且打开后,往里面写入字符串,然后关闭退出。读进程代码如下: #include #include #include #include #include #include #define FIFO "/tmp/fifo" #define MAX_LEN 128 int main(void) { int readFd,n; char line[MAX_LEN] = {0}; /*打开FIFO,这里打开可能失败,应该要对返回值处理*/ readFd = open(FIFO,O_RDONLY,0); /*从FIFO读取数据*/ n = read(readFd,line,MAX_LEN); printf("read %d bytes from pipe :%s\n",n,line); close(readFd); /*删除FIFO*/ unlink(FIFO); return 0; }它先打开一个已知的FIFO,然后从FIFO中读取数据。 在一个终端先运行写进程,然后运行读进程。
两个没有亲缘关系的进程可以通过FIFO进行通信。消息队列消息队列可以认为是一个消息链表,存储在内核中,进程可以从中读写数据。与管道和FIFO不同,进程可以在没有另外一个进程等待读的情况下进行写。另外一方面,管道和FIFO一旦相关进程都关闭并退出后,里面的数据也就没有了,但是对于消息队列,一个进程往消息队列中写入数据后退出,另外一个进程仍然可以打开并读取消息。消息队列与后面介绍的UNIX域套接字相比,在速度上没有多少优势。信号量信号量是一个计数器,它主要用在多个进程需要对共享数据进行访问的时候。
考虑这一的情况,不能同时有两个进程对同一数据进行访问,那么借助信号量就可以完成这样的事情。它的主要流程如下:检查控制该资源的信号量如果信号量值大于0,则资源可用,并且将其减1,表示当前已被使用如果信号量值为0,则进程休眠直至信号量值大于0也就是说,它实际上是提供了一个不同进程或者进程的不同线程之间访问同步的手段。共享内存共享内存允许多个进程共享一个给定的存储区,由于它们是共享一块内存数据,因此其速度非常快。但是需要另外提供手段来保证共享内存的同步访问,例如它可以用到前面所提到的信号量来实现访问同步。UNIX域套接字UNIX域套接字和套接字很相似,但是它有更高的效率,因为它不需要执行协议处理,例如计算校验和,发送确认报文等等,它仅仅复制数据。当然,它也只适用于同一台计算机上的进程间通信。例如redis服务配置unixsocket启动后,通过redis-cli的-s参数就可以指定UNIX域套接字,连接到redis服务器。 $ redis-cli -s /tmp/redis.sock
redis /tmp/redis.sock>它会比使用网络套接字的速度要快。
网络套接字这个不用多说,它利用网络进行通信,与前面所提到的通信方式不同的是,它能用于不同计算机之间的不同进程间通信。总结本文简单介绍了进程间通信的常见方式,其中对管道和命名管道我们使用了一个例子来简单说明,因为我们可能会经常见到它。对于FIFO,最后一个引用它的进程终止时,留在FIFO的数据也将会被删除,而对于消息队列却不是这样,它会一直留到被显示删除或者系统自举,另外消息队列于其他方式相比并没有特别的优势。而信号量实际上常用于共享数据的同步访问。共享内存在进程间传递数据非常高效,但是系统没有对访问进行同步,因此还需要另外实现数据的访问同步。套接字(socket)是应该目前应用最广泛的进程间通信方式。
看完上述内容是否对您有帮助呢?如果还想对相关知识有进一步的了解或阅读更多相关文章,请关注亿速云行业资讯频道,感谢您对亿速云的支持。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。