進程是操作系統中一個很重要的概念。進程是操作系統分配資源的基本單位,也是CPU調度的基本單位。Linux作爲多任務系統,能夠同時運行幾個進程。通常各個進程必須保持獨立,避免彼此干擾。但是有時候,應用程序必須彼此通信。舉例來說:
1.一個進程生成的數據傳輸到另一個進程時
2.數據由多個進程共享時
3.進程必須彼此等待時
4.需要協調資源的使用時
進程是操作系統中一個很重要的概念。進程是操作系統分配資源的基本單位,也是CPU調度的基本單位。Linux作爲多任務系統,能夠同時運行幾個進程。通常各個進程必須保持獨立,避免彼此干擾。但是有時候,應用程序必須彼此通信。舉例來說:
1.一個進程生成的數據傳輸到另一個進程時
2.數據由多個進程共享時
3.進程必須彼此等待時
4.需要協調資源的使用時
進程間通信的幾個概念:
幾個進程在訪問資源時彼此干擾的情況通常稱之爲竟態條件。
進程的執行在不應該被中斷的地方被中斷,從而導致進程執行不正確。將相關的代碼段進行標記使之無法被調度器中斷,這段代碼就稱爲臨界區。
內核可以不受限制地訪問整個地址空間。在多處理器系統上(或類似地,在啓用了內核搶佔的單核處理器系統上),如果幾個處理器同時處於核心態,則理論上它們可以同時訪問同一個數據結構。內核爲了避免產生竟態提供了各種鎖選項,如原子操作、自旋鎖、信號量、讀寫鎖等。
Linux使用system V引入的機制,來支持用戶進程的進程間通信和同步。System V的3種進程間通信(IPC)機制包括了信號量、消息隊列、共享內存。
除了system V UNIX採用的IPC機制外,進程間還有其他的方法可以用來交換消息和數據。比如信號、管道和套接字等。
共享內存
共享內存可以說是最有用的進程間通信方式,也是最快的IPC形式。兩個不同進程A/B共享內存的意思是,同一塊物理內存被映射到進程A、B各自的進程地址空間。進程A可以看到進程B對共享內存中數據的更新。反之亦然。
共享內存方式之mmap():
mmap()函數及其相關係統調用的兩種方法
(1)使用普通文件提供的內存映射:適用於任何進程之間;需要打開或創建一個文件,然後再調用mmap()。
(2)用特殊文件提供匿名內存映射:適用於具有親緣關係的進程之間,由於父子進程特殊的親緣關係,在父進程中先調用mmap(),然後再fork,fork之後子進程繼承父進程匿名映射後的地址空間,同樣也繼承父進程mmap()返回的地址。
ION基本概念介紹
ION是Google的下一代內存管理器,用來支持不同的內存分配機制,如CARVOUT(PMEM),物理連續內存(kmalloc), 虛擬地址連續但物理不連續內存(vmalloc), IOMMU等。ION將內核態形形色色的內存分配納入統一的管理接口之中,更重要的設計意圖是爲內存在不同用戶態進程之間傳遞和訪問提供了支持。
需要注意的問題:
1.文件描述符的傳遞
在不具有親緣關係的兩個進程間需要傳遞文件描述符時,單純的傳遞一個int型的fd是沒有任何實際意義的,對於進程間通信傳遞描述符時需要採用套接字的方法。
ion機制這樣通過套接字傳遞文件描述,使用mmap函數進行內存映射,使得兩個進程共享了同一片內存。兩個不具有親緣關係的進程也實現了匿名映射。
套接字是操作系統內核中的一個數據結構,它是網絡中的節點進行相互通信的門戶,是網絡進程的ID。網絡通信歸根到底還是進程間的通信(不同計算機上的通信)。UNIX域套接字可以在同一臺主機上各進程間傳遞文件描述符。
相關API:
#include <sys/types.h>
#include <sys/socket.h>
ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags);
ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);
ION進程間通信的用法示例:
進程B:
int size = 0x1000
ion_fd = open("/dev/ion", O_RDONLY);
fd_data.fd = get_share_fd();
ret = ioctl(ion_fd, ION_IOC_IMPORT, &fd_data);
mem = (unsigned char *)mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd_data.fd, 0);//mmap
進程A:
int ionfd = open(“/dev/ion”, O_RDONLY); //打開設備節點
alloc_data.len = 0x1000; //填充結構體
alloc_data.align = 0;
alloc_data.heap_id_mask = ION_HEAP_TYPE_DMA_MASK;
alloc_data.flags = 0;
rc = ioctl(ionfd,ION_IOC_ALLOC, &alloc_data);
fd_data.handle = alloc_data.handle;
/*映射內存*/
mem = mmap(NULL, alloc_data.len, PROT_READ|PROT_WRITE, MAP_SHARED, fd_data.fd, 0);
rc = ioctl(ionfd,ION_IOC_SHARE,&fd_data);//得到文件描述符的副本用傳遞給進程B
shared_fd = fd_data.fd;