进程与线程:
进程:活动的程序。拥有独立的地址空间。一个程序至少有一个进程,一个进程至少有一个线程。
线程:不能独立运行,各线程共享进程的内存地址。
Linux 中进程和线程的实现是基本相同的,如果两个线程的 pid 是相同的,那么他们则属于同一个进程。
上下文切换:进程和线程上下文切换都需要保存程序计数器、栈。但是由于进程间的逻辑地址空间是不同的,所以上下文切换时还需要保存地址空间,比如 page cache, memory map,反之线程不需要保存地址空间。
进程低地址 0~4 k 是保留的,禁止任何形式的访问。所以,通过 NULL 访问时,会直接 coredump,再比如访问 0x1、0x2 地址也会 crash.
进程间通信(IPC):
1、管道:半双工通信,数据单向流动,没有名字且大小受限,只能在亲属进程间通信,传输无格式流,所以通信双方必须事先约定好数据格式,存储在内存中;
2、有名管道:有名字,半双工,允许非亲属进程间通信,FIFO,有自己的传输格式,是一个设备文件,存储在文件系统中;
3、消息队列:放在内核中的消息链表,只有内核重启(系统重启)才能删除一个消息队列,大小受限。
4、信号:软件层次上对中断的模拟。唯一的异步通信机制,用于通知接收进程某个事件已经发生。
5、信号量:计数器,控制多个进程对于共享数据(临界区)的访问。只能通过PV操作改变,P操作信号量减1,如果结果大于0,则可以继续访问;V操作,信号量加1,如果结果大于0,则可以访问。当信号量大于0时,表示可供并发进程访问的临界资源数;当小于0时,表示正在等待使用临界资源的进程数。
6、共享内存:最有用、最快的IPC形式。通过系统函数映射一块可以被其他进程访问的内存(因为进程中是逻辑地址,要与物理地址对应)。同步可以选互斥锁和信号量。因为进程可以直接访问共享内存,不需要在内核与用户空间进行数据拷贝,所以效率高。共享内存一直保持存在于内存,往往在解除映射才写回文件。
7、套接字:可以网络通信。
相关函数:fork,创建子进程;clone,创建线程;thread构造函数,创建线程;
shmget,创建共享内存;shmat,启动对共享内存的访问,并把共享内存连接到当前进程的地址空间;shmdt,将共享内存从当前进程中分离;shmctl,共享内存管理。
c/c++ linux 进程间通信系列4,使用共享内存 - 小石王 - 博客园
线程间通信:
全局变量,互斥锁,条件变量,事件(future?)