多进程,多线程总结
1)
进程同步有:
信号signal,无名管道,有名管道,消息队列,信号量,共享内存,socket,文件等
线程同步有:
线程数据(pthread_key_t),互斥锁(mutex),条件变量,信号灯,pthread_join.
进程间通信(System V)
管道,消息队列,信号量,共享内存
1.管道:
无名管道应用于父子进程间.
有名管道以文件的形式存储于磁盘等外部存储设备中,可以在任意两个进程中应用.
2.System V消息队列
System V消息队列采用msgid_s结构管理消息队列.
msgget,msgsnd,msgrcv,msgctl.
采用消息队列通信比管道通信具有更多的灵活性,通信的进程不但没有血缘上的要求,也不需要进行同步处理.发送进程可以在任意时
候写入消息,也可以在接收开始之前结束执行,而使用管道,如果是无名管道还是有名管道,通信的两个进程必选是正在运行的进程.
消息队列有如下特变
a消息队列提供了消息数据的自动拆分功能,同时不能接收两次发送的消息
b引入消息类型,一个消息队列在逻辑上可以拆分为多个不同消息类型的链表.
c消息队列提供了完全异步的读写服务.管道在使用时要求读写两端同时被打开,而消息队列没有这个限制,
在系统中获取当前IPC对象信息的命令有ipcs,删除系统中当前IPC对象的命令有ipcrm等.创建消息队列的函数有msgget,发送消息队
列的函数有msgsnd,从消息队列中接收消息的函数有msgrcv,控制消息队列的函数有msgctl,它可以实现查询消息队列数据结构,改变
消息队列访问权限,改变消息队列属主信息和删除消息队列等功能.
3 Syetem V信号量
信号量本质上是一组整形变量,信号量是为了控制临界资源而产生的一个或一组计数器,在本质上是一个整形变量.
P操作:进程申请临界资源时发出P操作,检查信号量取值,如果该值大于0,则分配资源,信号值减1,否则代表当前无空余资源,进程阻塞
,直到指定资源到达为止.
V操作:进程释放临界资源时发出V操作,释放临界资源信号量取值加1.
Z操作:测试操作,等待当前信号量取值为0,如果成立,进程返回,否则阻塞直到条件成立.
Unix采用semid_ds结构来管理信号量
semget,semctl,semop
创建或访问信号量的函数有semget,操作信号量的函数有semop,控制信号量的函数有semctl,它可以获取信号量函数状态,信号量的取
值,信号量上阻塞的进程数等信息,也可以删除信号量和设置信号量取值.
4 System V共享内存
共享内存的应用模型包括创建,映射,读写和释放等四个步骤.
共享内存是最快捷的进程间通信方式,它被进程映射后作为普通内存使用,不需要额外的read和write函数.
unix的内核采用结构shmid_ds来管理共享内存.
在进程中使用共享内存,首先需要调用函数shmget创建或者获取共享内存的标识,然后调用shmat函数将该共享内存映射到进程地址空
间,如果进程不再需要访问共享内存,可以调用shmdt释放映射.
shmget,shmat,shmdt完成
共享内存就是物理内存中一段可被多个进程共享访问的区域,是最快的IPC对象,创建或访问共享内存的函数有shmget,映射共享内存
的函数有shmat,释放共享内存的函数有shmdt,控制共享内存的函数有shmctl,它可以获取和设置共享内存的基本信息,删除共享内存,
锁定和释放共享内存.
Posix
使用互斥锁需要注意的几点
a)互斥量需要时间来进行加锁和解锁.所以互斥量应尽量少,够用即可.
b)互斥量本身是串行执行,如果很多线程需要频繁的加锁同一个互斥量,则线程的大部分时间就会等待,这对性能是有害的.如果互斥
量保护的数据或代码保护彼此无关的片段,则可以把特大的互斥量分解成几个小的互斥量来提高性能.
条件变量
互斥锁的一个明细的缺点是它只有两种状态:锁定和非锁定.而条件变量允许线程阻塞和等待另一个线程发送信号的方法弥补了互斥
锁的不足.它常和互斥锁一起使用.使用时,条件变量被用来阻塞一个线程,当条件变量不满足时,线程往往解开相应的互斥锁并等待条
件发送变化.一旦其它某个线程改变了条件变量,它将通知相应的条件变量唤醒一个或多个正被此条件变量阻塞的线程.
条件变量是利用线程间共享的全局变量进行同步的一种机制,主要包括两个动作:一个线程等待"条件变量的成立"而挂起,另一个线程
使"条件成立".为了防止竞争,防止多个线程同时请求pthread_cond_wait()或者pthread_cond_timedwait()的竞争条件,条件变量的
使用总是和一个互斥锁结合一起.
没有条件变量,开发者需要线程不停的轮询以查询条件是否满足,因为线程要不停的忙等,会消耗很多资源.条件变量就是不用轮询而
能达到同样目的的方法.
Posix共享内存
共享内存是最快的IPC形式,它允许多个不相关的进程去访问同一部分逻辑内存.如果需要在两个运行的进程间传输数据,共享内存将
是一种效率极高的解决方案.一旦这样的内存映射到共享它的进程的地址空间,这些进程间数据的传输就不在涉及内核,这样就可以减
少系统调用的时间,提高程序效率.
共享内存是由IPC为一个进程创建的一个特殊的地址范围,它将出现在进程的地址空间中,其它进程可以把同一段共享内存段连接到他
们自己的地址空间中去.所有进程都可以访问共享内存中的地址.如果一个进程向这段共享内存写了数据,所做的改动会立刻被有访问
同一段共享内存的其他进程看到.
注意的是共享内存本身没有提供任何同步功能,也就是说,在第一个进程结束对共享内存的写操作之前,并没有什么自动功能能够防御
第二个进程开始对它进行读操作.共享内存的访问同步问题必选由程序员负责,可选的同步方式有互斥锁,变量变量,读写锁,记录锁,
信号灯等.
Posix共享内存函数涉及两个步骤:
a)指定一个名字参数调用shm_open,以创建一个新的共享内存对象或者打开一个已经存在的共享内存区对象
b)调用mmap把这个共享内存区映射到调用进程的地址空间,传递到shm_open的名字参数随后由希望共享该内存区的任何其他进程使用
.