Linux 进程间通信知识点总结由刀豆文库小编整理,希望给你工作、学习、生活带来方便,猜你可能喜欢“linux进程间通信总结”。
Linux 进程间通信知识点总结
进程间通信(IPC)是指在不同进程之间传播或交换信息。进程间通信的方式主要有以下6钟:(1)管道(Pipe)(2)信号(Singal)(3)信号量(Semaphore)(4)共享内存(shared memory)(5)消息队列(Meage Queue)(6)套接字(Socket)下面对6种方式进行详细介绍:
管道
1、管道分为有名管道和无名管道,通常指无名管道。
2、无名管道特点:
(1)它是半双工的(即数据只能在一个方向上流动),具有固定的读端和写端。(2)它只能用于具有亲缘关系的进程之间的通信(也是父子进程或者兄弟进程之间)。
(3)对于它的读写也可以使用普通的read、write 等函数。但是它不是普通的文件,并不属于其他任何文件系统,并且只存在于内存中。
3、缺点:速度慢,容量有限,只有父子进程能通讯。
4、管道的创建及使用:
调用pipe()函数创建一个管道,再通过fork()函数创建一个子进程,该子进程继承父进程所创建的管道,为实现父子进程间的读写,只需把无关的读端或写端的文件描述符关闭即可。若要数据流从父进程流向子进程,则关闭父进程的读端(fd[0])与子进程的写端(fd[1]);反之,则可以使数据流从子进程流向父进程。
5、父子进程在运行时,先后顺序并不能保证。可以在进程中添加sleep()函数。
6、标流管道:管道的操作也支持基于文件流的模式,这种基于文件流的管道主要是用来创建一个连接到另一个进程的管道,这里的“另一个进程”也就是一个可以进行一定操作的可执行文件。
7、因此标准流管道就将一系列的创建过程合并到一个函数popen()中完成。它所完成的工作有以下几步:
(1)创建一个管道(2)fork()一个子进程
(3)在父进程中关闭不必要的文件描述符(4)执行exec函数族调用(5)执行函数中所指定的命令
8、popen()函数的使用减少了代码的编写量,但是灵活性不如pipe()函数所创建的管道,并且使用popen()创建的管道必须使用标准I/O函数进行操作,但不能使用read()、write()一类不带缓冲的I/O函数。open()创建的流管道必须使用函数pclose()来关闭该管道流。
9、有名管道特点:有名管道也是半双工的通信方式,但是它允许无亲缘关系进程间的通信。它是一个设备文件,提供一个路径名与FIFO关联。
10、有名管道缺点:任何进程间都能通讯,但速度慢。
11、使用有名管道需先调用open函数将其打开,设置读写端的权限,若只是以只读或只写方式打开,会阻塞到有读或写方式打开管道为止。若同时以读写方式打开,一定不阻塞。
12、有名管道的阻塞打开和非阻塞打开:(1)读进程
① 若管道阻塞打开,且当前FIFO内没有数据,则读进程一直阻塞到有数据写入。
② 若管道非阻塞打开,不论FIFO内是否有数据,读进程都立刻执行读操作。即FIFO内没有数据,该函数就立刻返回0。(2)写进程
① 若管道阻塞打开,写操作一直阻塞到有数据可以被写入。
② 若管道是非阻塞打开且不能写入全部数据,读操作进行部分写入或者调用失败。
13、除了调用myfifo()函数之外,有名管道还可以通过 “mknod 管道名 p”的方式创建。
信号
1、信号是软件层次上对中断机制的模拟,是一种异步通信方式。
2、信号值在32之前有不同的名称,在32后都是以“SIGRTMIN”和“SIGRTMAX”开头的,这是两类典型的信号量。
3、信号主要作为进程间以及同一进程不同线程之间的同步手段。
4、一个完整的信号生命周期可以分为3个阶段,这个3个阶段由4个重要事件来表示:信号的产生、信号在进程中注册、信号在进程中注销、执行信号处理函数。
5、发送信号的函数主要有kill()、raise()、alarm()以及pause()。kill()函数:中止进程,向进程发送其他信号。raise()函数:允许进程向自身发送信号。
alarm()函数:在进程中设置一个定时器,当定时器指定时间到时,就会向进程发送SIGALARM信号。pause()函数:将调用进程挂起直至捕捉到信号为止,通常用于判断信号是否移到。
6、信号的处理方法:(1)Singal():
可以用函数signal注册一个信号捕捉函数。原型为: #include
typedef void(*sighandler_t)(int);sighandler_t signal(int signum, sighandler_t handler);
signal 的第1个参数signum表示要捕捉的信号,第2个参数是个函数指针,表示要对该信号进行捕捉的函数,该参数也可以是SIG_DEF(表示交由系统缺省处理,相当于白注册了)或SIG_IGN(表示忽略掉该信号而不做任何处理)。signal如果调用成功,返回以前该信号的处理函数的地址,否则返回 SIG_ERR。
sighandler_t是信号捕捉函数,由signal函数注册,注册以后,在整个进程运行过程中均有效,并且对不同的信号可以注册同一个信号捕捉函数。该函数只有一个参数,表示信号值。(2)Sigaction(): 函数原型:
#include int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);sigaction也用于注册一个信号处理函数。参数signum为需要捕捉的信号;参数 act是一个结构体,里面包含信号处理函数地址、处理方式等信息。
参数oldact是一个传出参数,sigaction函数调用成功后,oldact里面包含以前对signum的处理方式的信息。
如果函数调用成功,将返回0,否则返回-1。
信号量
1、信号量是一个计数器,用于实现进程间的互斥与同步,而不是用于存储进程间通信数据。
2、信号量的值是指当前可用资源的数量,通常是对信号量进行PV操作。
P操作:有资源时候(信号量值 > 0)则占用一个资源(信号量减1);若没有资源(信号量 = 0),则被阻塞直到系统将资源分配给该进程(进入等待队列,一直等到资源轮到该进程)。
V操作:若等待队列中有进程在等待资源,则唤醒一个阻塞进程。如果没有进程等待它,则释放一个资源(给信号量值加1)。
3、缺点:不能传递复杂消息,只能用来同步。
4、信号量的应用步骤:
(1)创建信号量或获得在系统中已存在的信号量--semget()(2)初始化信号量--semctl()的SETVAL操作,信号量初始化为1(3)对信号量进行PV操作--semop()
(4)删除无用的信号量--semclt()的IPC_RMID操作
5、在实例中,通常是先对父进程执行操作,但由于信号量处置为0父进程阻塞,转至执行子进程,在子进程执行结束后方可执行父进程操作。如果不加信号量,则父进程会先执行完毕。
共享内存
1、共享内存是指两个或多个进程共享一个给定的存储区。是进程间通信最快的方式。
2、特点:
(1)共享内存是最快的一种 IPC,因为进程是直接对内存进行存取。(2)因为多个进程可以同时操作,所以需要进行同步。
(3)信号量+共享内存通常结合在一起使用,信号量用来同步对共享内存的访问。
3、使用流程
(1)创建共享内存 shmget()(2)映射共享内存 shmat()(3)撤销映射 shmdt()
4、使用实例:
首先创建一个共享内存区,之后创建子进程,在父子进程中将共享内存分别映射到各自的进程地址空间中。父进程等待用户输入,将键入的数据写入到共享内存中,之后往共享内存的头部写入标识字符串表示父进程成功写入数据。子进程一直等到共享内存的头部字符串为标识字符,然后将其打印在屏幕上。父子进程完成以上操作后,分别解除与共享内存的映射关系。最后在子进程中删除共享内存。
消息队列
1、消息队列就是消息的列表,用户可以从中添加消息和读取消息。消息存在于内核中,由队列ID来标识。它在系统内核中是以消息链表的形式出现,消息链表中节点的结构用msg声明。
2、消息队列的实现包括打开消息队列、添加消息、读取消息和控制消息队列这4种操作。(1)创建或打开消息队列
msgget()(2)添加消息
msgsnd()(3)读取消息
msgrcv()----同FIFO不同的是,这里可以指定取走某一条消息(4)控制消息队列
msgctl()
3、消息的发送端和接收端不需要额外的实现进程间的同步。发送端发送的消息类型设置为该进程的进程号,接收端根据消息类型确定消息发送者的类型号。
4、优点:消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点。
5、缺点:容量受到系统限制,且要注意第一次读的时候,要考虑上一次没有读完数据的问题
套接字
1、socket是一种文件描述符,不仅可实现本机上进程的通信,还可以实现不同机器间的进程通信。
2、套接字的特性有三个属性确定,它们是:域(domain),类型(type),和协议(protocol)。
3、套接字域指定套接字通信中使用的网络介质。最常见的套接字域是 AF_INET(IPv4)或者AF_INET6(IPV6),它是指 Internet 网络。
4、套接字类型:流套接字、数据报套接字、原始套接字。
5、套接字协议有TCP协议和UDP协议。TCP协议可靠性高可减少错误发生的概率,UDP协议灵活性高可减少网络负荷。
6、通信机制:
首先服务端建立socket套接字可使得其可接受客户端socket套接字请求,然后调用bind绑定函数,将本机IP地址和本地监听与客户端相连的端口号绑在一起,形成半相关的套接字。再运行客户端,也使得本机IP地址和端口号绑定,可向服务端发送请求。然后即可监听客户端向服务端发送的连接请求,若有请求accept,无请求则一直监听。此时服务端和客户端可进行双向通信。通信结束后关闭通道。
7、网络高级编程:
(1)作用:解决I/O多路复用(2)fcntl():
fcntl可实现对指定文件描述符的各种操作,其函数原型如下:int fcntl(int fd, int cmd,.../* arg */);
操作类型由cmd决定。cmd可取如下值: F_DUPFD:复制文件描述符
F_DUPFD_CLOEXEC:复制文件描述符,新文件描述符被设置了close-on-exec F_GETFD:读取文件描述标识 F_SETFD:设置文件描述标识 F_GETFL:读取文件状态标识 F_SETFL:设置文件状态标识
F_GETLK:如果已经被加锁,返回该锁的数据结构。如果没有被加锁,将l_type设置为F_UNLCK F_SETLK:给文件加上进程锁
F_SETLKW:给文件加上进程锁,如果此文件之前已经被加了锁,则一直等待锁被释放。(3)select():
与fcntl函数相比,减少了不必要的CPU资源的占用。可以设置等待时间。