Linux下进程间通信

来源:互联网 发布:淘宝客宣传语 编辑:程序博客网 时间:2024/06/11 11:29
进程间的通信
进程间通信的难点:
-独立的进程地址空间
-异步工作

常用的进程间通信机制
-管道(Pipe)及有名管道(name pipe):进程间建立字节流队列。
-消息队列(Message Queue):进程间建立消息队列
-信号(Signal):信号是在软件层次上对中断机制的一种模拟。一个进程可以向另一个进程发送信号,就像外设触发了CPU的中断。
-共享内存(Shared memory):将同一块物理内存映射到两个不同进程的地址空间中
-信号量(Semaphore):主要是作为进程之间的同步和互斥手段

-套接字(Socket):这是一种更为一般的进程间通信机制,它可用于网络中不同机器上的两个进城之间的进程间通信,应用非常广泛。

管道主要包括两种:无名管道和有名管道
-无名管道特点
*只能用于具有亲缘关系的进城之间的通信(父子进程或者兄弟进程)
*半双工的通信模式,具有固定的读端和写端
*管道也可以看成是一种内存中的特殊文件,对于他的读写也可以使用普通的read()、write()等函数
-有名管道特点

*他可以使互不相关的两个进程实现彼此通信

*对应一个实际的文件,并且在文件系统中是可见的。在建立了管道之后,两个进程就可以把它当作普通文件一样
进行读写操作,使用非常方便。
*严格地遵守先进先出的规则,对管道的度总之从开始处返回数据,对他们的写则是把数据添加到末尾,因此不支持如lseek()等文件定位操作。

关于无名管道的系统调用
-管道创建和关闭
*管道是基于文件描述符的通信方式,当一个管道建立时,它会创建两个文件描述符fds[0]和fds[1],其中fds[0]
固定用于读管道,而fd[1]固定用于写管道,这样就构成可一个半双工的通道。
*管道关闭时只需将这两个文件描述符关闭即可,可使用普通的close()函数逐个关闭各个文件描述符。

-无名管道读写注意点:

只有在管道的读端存在是,向管道写入数据才有意义。否则,向管道写入数据的进程将收到内核传来的SIGPIPE信号
向管道写入数据时,Linux将不保证写入的原子性,管道缓冲区一有空闲区域,写进程就会试图向管道写入数据。
如果读进程不读取管道缓冲区中的数据,那么些操作将会一直阻塞。
如果管道缓冲区是空,那么读进程将会一直阻塞

有名管道(FIFO)
-有名管道可以实现任意连个进程之间的通信,并不限制两个进程间有亲缘关系
-有名管道作为一种特殊的文件存放在文件系统中,使用完仍然存在,除非对其进行删除
-有名管道也只能用于单向传输

有名管道
-FIFO读写
对于进程
-若该管道是阻塞打开,且当前FIFO内没有数据,则读进程而言将一直阻塞到有数据写入
-若该管道是非阻塞打开,则不论FIFO内是否有数据,读进程会立即执行读操作,即如果FIFO内没有数据,读函数都会立刻返回0
对于进程
-若该管道是阻塞打开,则写操作将一直阻塞到数据可以被写入
-若该管道是非阻塞打开而不能写入全部数据,则读操作进行部分写入后者调用失败。

Linux信号机制是在应用软件层次对中断机制的一种模拟,是一种异步通信方式
每个进程都有一个自己私有的信号处理函数映射表,当该进程收到一个信号时,对应的信号处理函数被触发执行
一个进程可以向另一个进程发送信号,也可以向自己发送信号,咋偶哦系统内核页可以向一个进程发送信号,以
通知某些硬件事件。
信号处理函数映射表共有64个表项。前32个信号,编号为0-31,有预定义的含义和处理函数;后32个作为扩充。
前32个是不可靠信号,后32个为可靠信号。不可靠信号和可靠信号的区别在于前者不支持排队,可能会造成信号
丢失,而后者不会。

信号发送:kill() raise()
kill系统命令是kill()函数一个用户接口,它不仅可以终止进程(实际上发出SIGKILL信号),也可以向进程发送其他信号。

raise()函数允许进程向其自身发送信号
信号捕捉:alarm() pause()
alerm()也称为闹钟函数,他可以在进程中设置一个定时器,当定时器指定的时间到时,他就可以向进程发送SIGALARM信号。
pause()函数是用于将调用进程挂起直至捕捉到信号为止(该信号没有被阻塞)。
信号的处理:signal、sigaction

信号量
-信号量是用来共享资源的种进程访问机制,是的共享资源在一个时刻只有一个
-信号量对应于某一种资源,取一个非负的整型值。信号量指的是当前可用的该资源的数量,若他等于0则意味着者目前没有可用的资源。
-针对信号量的操作:
P操作:如果有可用的资源(信号量值>0),则占用一个资源(给信号量值减去-,进入临界区代码),如果没有可用资源(信号量等于0),

则进入到该信号量的等待队列中并阻塞休眠,直到系统将其唤醒。
V操作:如果在该信号量的等待队列中有进程在等待资源,则唤醒一个阻塞进程。如果没有进程等待它,则释放一个资源。


使用信号量的步骤
第一步:创建信号量或获得系统已存在的信号量,此时需要调用semget()函数。不同进程通过使用同一个信号量
键值来获取同一个信号量。
第二步:初始化信号量,此时使用semctl()函数的SETVAL操作。当使用二维信号量时,通常将信号量初始化为1
第三步:进行信号量的PV操作,此时调用semop()函数。这一步是实现进程之间的同步和互斥的核心工作部分
第四步:如果不需要信号量,则从系统中删除它,此时使用semctl函数的IPC_RMD操作。此时需要注意,在程序中
不应该出现对已经被删除的信


共享内存是一种最为高效的进程间通信方式,进程可以直接读写内存,而不需要任何数据的拷贝

*为了在多个进程间交换信息,内核专门留出了一块内存区,可以有需要访问的进程将其映射到自己的私有地址空间
*进程就可以直接读写这一内存区而不需要进行数据的拷贝,从而大大提高效率。
*由于多个进程共享一段内存,因此也需要依靠某种同步机制,如互斥锁和信号量等。

实现共享内存的步骤
-创建共享内存,这里用到的函数是shmget,也就是从内存中获得一段共享内存区域
-映射到共享内存,也就是把这段创建的共享内存映射到具体的进程空间中去,这里使用的函数是shmst
-到这里,就可以使用这段共享内存了,也就是可以使用不带缓冲的I/O读写命令对其进行操作
-撤销映射的操作,其函数为shmdt
-删除共享内存使用shmctl函数。

消息队列
消息队列就是一些消息的列表。用户可以在消息队列中添加消息和读取消息。消息队列具有一定的FIFO特性,但
是它可以实现消息的随机查询,比FIFO具有更大的优势。同时这些消息又是存在于内核中的,由"队列ID"来表示。


消息队列的实现包括创建或打开消息队列、添加消息、读取消息和控制消息队列这4种操作。
创建会打开消息队列使用的函数是msgget,这里创建的消息队列的数量谁受到系统消息队列数量的限制。
添加消息使用的函数是msgsnd函数,他爸消息添加到已打开的消息队列末尾
读取消息使用的函数是msgrcv,他把消息从消息队列中取走,与FIFO不同的是,这里可以指定取走某一条消息
控制消息队列使用的函数是msgctl,塔尔可以完成多项功能。


0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 在国外手机软件好多不支持怎么办 淘宝店拒绝退款怎么办 app没有退款资格怎么办 手机无法计步怎么办 抖音机型不支持怎么办 用nfc不支持卡片怎么办 移动怎么办省内流量包 手机交不了话费怎么办 淘宝快递不签收怎么办 快递买家不签收怎么办 淘宝退货未收货怎么办 淘宝退衣服运费怎么办 手机流量不到账怎么办 淘宝水果坏了怎么办 用微信充值话费充成空号了怎么办 苹果id被拉黑了怎么办 苹果app不退款怎么办 合同退款不退怎么办 微信充值q币被骗怎么办 小米手机存储空间不够怎么办 小米mix2s存储空间不够怎么办 进货一直没发票怎么办 魅蓝note5卡怎么办 电话费套餐花不了怎么办 墙和床头有间缝怎么办 床板里有虫子怎么办 松木床板味道大怎么办 寝室床板有虫子怎么办 胶合板当床板有气味怎么办 淘宝食品有问题怎么办 淘宝买东西碎了怎么办 被淘宝商家骚扰怎么办 闲鱼被别人拉黑怎么办 三无工厂抓到怎么办 淘宝买东西卖家不发货怎么办 打假人异地起诉怎么办 卖家拒绝发货怎么办 千牛发货收费怎么办 淘宝购物想退货怎么办 天猫超市发货怎么办 驾校退款乱收怎么办