进程间通信方式总结
Posted jiangyu0331
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了进程间通信方式总结相关的知识,希望对你有一定的参考价值。
一、简单的进程间通信
1.命令行参数:argc argv;
2.环境变量
3.信号signal
signal信号机制是属于计算机异常处理机制中的一种。
signal信号属于一种异步处理异常的机制之一。
不可靠信号:小于34,不支持排队,可能会丢失。
可靠信号:34-64,支持排队,不会丢失。
未决信号:处于递送阶段的信号状态 处于未决状态的不可靠信号只有一份,相同的可靠信号可以有多份。
函数:sigqueue(对不可靠的信号不做排队,会丢失信号) | sigaction。
signal(SIGINT,signet); ---SIGINT 信号码,signet信号处理函数 :SIG_IGN忽略该信号,SIG_DFI默认处理函数。
子进程会继承父进程的信号处理方式,直到子进程调用exec函数。
发送信号的方式:
① 键盘 : Ctrl+C 中断 Ctrl+ 退出 Ctrl+Z 暂停;
② 错误;
③ 命令 (kill -信号 进程号);
④ 函数 kill(pid,sig)
pid>0,向进程发送sig信号;
pid=0,向同进程组的所有进程发送信号;
pid=-1,向所有进程发送信号;
pid<-1,向绝对值等于pid 的进程组发送信号。
常用还有raise, alarm和setitimer以及sigqueue等函数。
4.文件
① 使用文件也可以完成IPC,理论依据是,fork后,父子进程共享文件描述符。也就共享打开的文件。
父子进程共享打开的文件。借助文件进行进程间通信(可先打开文件,再创建子进程)。
② 另外,无血缘关系的进程也可以打开同一个文件进行通信,方法一样,因为这些进程打开的是同一个进程。
其实在打开文件时(调用open时),操作系统内核就调用了mmap。
因为一个文件只有一个文件结构体(FILE),打开时位于内核,被打开这个文件的多个进程共享。
二、传统的进程间通信方式---管道
1.无名管道 适用于父子进程之间的通信
通过输出参数pipefd返回两个文件描述符,其中pipefd[0]用于读,pipefd[1]用于写。
一般用法 :
① 调用该函数在内核中创建管道文件,并通过其输出参数,获得分别用于读和写的两个文件描述符;
② 调用fork函数,创建子进程;
③ 写数据的进程关闭读端(pipefd[0]),读数据的进程关闭写端(pipefd[1]);
④ 传输数据;
⑤ 父子进程分别关闭自己的文件描述符。
2.有名管道 基于有名文件(管道文件)的管道通信。
① 命令形式
# mkfifo fifo
# echo hello > fifo # cat fifo
② 编程模型
创建管道:mkfifo
打开管道:open
读写管道:read/write
关闭管道:close
删除管道:unlink
三、共享内存
1.特点:
① 两个或者更多进程,共享同一块由系统内核负责维护的内存区域,其地址空间通常被映射到堆和栈之间。
② 无需复制信息,最快的一种IPC机制。
③ 需要考虑同步访问的问题。
④ 内核为每个共享内存,维护一个shmid_ds结构体形式的共享内存对象。
2.实现方式:
共享内存模型会建立起一块供协作进程共享的内存区域,由需要访问的进程将其映射到自己的私有地址空间,
进程就可以直接读写这一内存区来进行交换信息,不用再进行数据的拷贝。
创建/获取共享内存 :int shmget (key_t key, size_t size, int shmflg);
加载共享内存 :void* shmat (int shmid, const void* shmaddr,int shmflg);
卸载共享内存 :int shmdt (const void* shmaddr);
销毁/控制共享内存 :int shmctl (int shmid, int cmd, struct shmid_ds* buf);
四、消息队列
1.特点:
① 消息队列是一个由系统内核负责存储和管理,并通过消息队列标识引用的数据链表。
② 可以通过msgget函数创建一个新的消息队列,或获取一个已有的消息队列。
通过msgsnd函数向消息队列的后端追加消息,通过msgrcv函数从消息队列的前端提取消息。
③ 消息队列中的每个消息单元除包含消息数据外,还包含消息类型和数据长度。
④ 内核为每个消息队列,维护一个msqid_ds结构体形式的消息队列对象。
2.实现方式:
消息队列的本质就是由内核创建的用于存放消息的链表,由于是存放消息的,所以我们就把这个链表称为了消息队列。
通信的进程通过共享操作同一个消息队列,就能实现进程间通信。
创建/获取消息队列 :int msgget (key_t key, int msgflg);
向消息队列发送消息 :int msgsnd (int msqid, const void* msgp,size_t msgsz, int msgflg);
从消息队列接收消息 :ssize_t msgrcv (int msqid, void* msgp, size_t msgsz,long msgtyp, int msgflg);
销毁/控制消息队列 :int msgctl (int msqid, int cmd, struct msqid_ds* buf);
五、信号量集
信号量组成的集合 进程间通信的方式 限制对共享资源进行访问的进程数量
1.特点:
① 计数器,用于限制多个进程对有限共享资源的访问。
② 多个进程获取有限共享资源的操作模式
A. 测试控制该资源的信号量;
B. 若信号量大于0,则进程可以使用该资源,为了表示此进程已获得该资源,需将信号量减1;
C. 若信号量等于0,则进程休眠等待该资源,直到信号量大于0,进程被唤醒,执行步骤A;
D. 当某进程不再使用该资源时,信号量增1,正在休眠等待该资源的其它进程将被唤醒。
2.实现方式:
创建/获取信号量 :int semget (key_t key, int nsems, int semflg);
操作信号量 :int semop (int semid, struct sembuf* sops,unsigned nsops);
销毁/控制信号量:int semctl (int semid, int semnum, int cmd);
int semctl (int semid, int semnum, int cmd,union semun arg);
六、socket
socket,即套接字,是一种通信机制,凭借这种机制,客户/服务器(即要进行通信的进程)系统的开发工作既可以在本地单机上进行,也可以跨网络进行。也就是说它可以让不在同一台计算机但通过网络连接计算机上的进程进行通信。也因为这样,套接字明确地将客户端和服务器区分开来。
socket通信步骤
1.服务器:
① 创建socket套接字 准备地址和端口
② bind 将socket套接字与地址端口绑定
③ listen 设置为监听状态
④ accept 阻塞等待连接
⑤ recv/send 发送接收数据
⑥ close 关闭
2.客户端:
① 创建socket套接字 准备地址和端口
② bind 将socket套接字与地址端口绑定
③ connect与服务器连接
④ recv/send 发送接收数据
⑤ close 关闭
socket具体的之后还需要补充。
以上是关于进程间通信方式总结的主要内容,如果未能解决你的问题,请参考以下文章