嵌入式系统与单片机|技术阅读
登录|注册

您现在的位置是:嵌入式系统与单片机 > 技术阅读 > 进程间通信的6种方法

进程间通信的6种方法

天气转暖,脱掉羽绒长衫,换上格子衬衫。我不但知道4种茴字写法,我还知道进程间通信的6种方法。6种!

从操作系统层面看进程通信:我们知道,为了保证安全,每个进程的用户地址空间都是独立的,一般而言一个进程不能直接访问另一个进程的地址空间,不过内核空间是每个进程都共享的,所以进程之间想要进行信息交换就必须通过内核

Linux 内核提供的常见的6种进程通信机制:
    • 管道 
    • 消息队列
    • 共享内存
    • 信号量
    • 信号
    • 套接字

介于泛泛介绍这几种通信的文章很多,这里我们也不再重复了。这里展开的是套接字(socket)如何实现进程间通信的。 

socket可以实现不同主机之间通信,也可以支持本地进程间通信。根据通信域的不同可以划分成:Unix domain socket 和 Internet domain socket。

Unix domain socket 又叫 IPC (inter-process communication) socket,用于实现同一主机上的进程间通信。socket 原本是为网络通讯设计的,但后来在 socket 的框架上发展出一种 IPC 机制,就是 UNIX domain socket。

注:虽然网络 socket 也可用于同一台主机的进程间通讯(通过 loopback 地址 127.0.0.1),但是 UNIX domain socket 用于 IPC 更有效率:不需要经过网络协议栈,不需要打包拆包、计算校验和、维护序号和应答等,只是将应用层数据从一个进程拷贝到另一个进程。这是因为,IPC 机制本质上是可靠的通讯,而网络协议是为不可靠的通讯设计的。

UNIX domain socket 是全双工的,API 接口语义丰富,相比其它 IPC 机制有明显的优越性,目前已成为使用最广泛的 IPC 机制,比如 X Window 服务器和 GUI 程序之间就是通过 UNIX domain socket 通讯的。Unix domain socket 是 POSIX 标准中的一个组件,所以不要被名字迷惑,linux 系统也是支持它的。

UNIX domain socket 使用上与internet domain socket的不同之处如下。

    • 创建socket

    // AF_UNIX, Local communication(本地,进程间通信)server_fd = socket(AF_UNIX, SOCK_STREAM, 0);
    • 绑定过程

    struct sockaddr_un server_address; server_address.sun_family = AF_UNIX; strcpy(server_address.sun_path, "./SocketIPCTest"); unlink("./SocketIPCTest"); server_len = sizeof(server_address);  //与网络编程不一样的地方是服务器端bind的时候用的是sockaddr_un结构,客户端connect的时候用的也是sockaddr_un结构,而不是sockaddr_in或sockaddr。  bind(server_fd, (struct sockaddr *)&server_address, server_len);


    服务器端代码

    #include<stdio.h>#include <stdlib.h>#include <string.h>#include <sys/un.h>#include <unistd.h>#include<sys/types.h>#include<sys/socket.h>
    int main(int argc,char *argv[]){ char buf[1024];  char send_msg[]="l am server!"; int msg_len; int server_fd,client_fd; int server_len,client_len; struct sockaddr_un server_address; struct sockaddr_un client_address; server_fd = socket(AF_UNIX, SOCK_STREAM, 0);
    server_address.sun_family = AF_UNIX; strcpy(server_address.sun_path, "./SocketIPCTest"); unlink("./SocketIPCTest"); server_len = sizeof(server_address); client_len = sizeof(client_address);
    bind(server_fd, (struct sockaddr *)&server_address, server_len); listen(server_fd,5); client_fd = accept(server_fd, (struct sockaddr *)&client_address,&client_len); while(1) { if(-1 == (msg_len = read(client_fd, buf, sizeof(buf)))) { perror("read"); exit(-1); } printf("recv msg is : %s\n",buf); if(-1 == (msg_len = write(client_fd, send_msg, sizeof(buf)))) { perror("write"); exit(-1); } printf("send_msg is : %s\n",send_msg); } close(server_fd); close(client_fd); return 0;}


    客户端代码

#include<stdio.h>#include <stdlib.h>#include <string.h>#include <sys/un.h>#include <unistd.h>#include <sys/types.h>#include <sys/socket.h>
int main(){ char send_msg[1024]; char recv_msg[1024]; int sockfd; int ret; int address_len,result; struct sockaddr_un address;
if(-1 == (sockfd = socket(AF_UNIX, SOCK_STREAM, 0))){ perror("socket"); return -1; }
address.sun_family = AF_UNIX; strcpy(address.sun_path, "./SocketIPCTest"); address_len = sizeof(address); result = connect(sockfd, (struct sockaddr *)&address,address_len); if(result == -1){ if(0 != access("./SocketIPCTest", F_OK)) { printf("[Warning]: Wait for Server socket Creating!!!\n"); usleep(500 * 1000); if(-1 == connect(sockfd, (struct sockaddr *)&address,address_len)){ perror("connect"); return -1; } }else{ perror("connect"); return -1; } } while(1) { memset(send_msg, 0, sizeof(send_msg)); scanf("%s",send_msg); ret = write(sockfd,send_msg,sizeof(send_msg)); if (ret <= 0) { perror("send\n"); } ret = read(sockfd,recv_msg, sizeof(recv_msg)); if (ret <= 0) { perror("read"); exit(-1); } printf("recv msg is %s\n",recv_msg); } return 0;}