日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

Linux 常见的六大 IPC 通信方式

發布時間:2025/6/15 linux 19 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Linux 常见的六大 IPC 通信方式 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Linux環境下,進程地址空間相互獨立,每個進程各自有不同的用戶地址空間。任何一個進程的全局變量在另一個進程中都看不到,所以進程和進程之間不能相互訪問,要交換數據必須通過內核,在內核中開辟一塊緩沖區,進程1把數據從用戶空間拷到內核緩沖區,進程2再從內核緩沖區把數據讀走,內核提供的這種機制稱為進程間通信(IPC,InterProcessCommunication)。今天我們來看一下,Linux下常見的六大IPC通信方式。

1、信號

信號是Unix/Linux系統在一定條件下生成的事件。信號是一種異步通信機制,進程不需要執行任何操作來等待信號的到達。信號異步通知接收信號的進程發生了某個事件,然后操作系統將會中斷接收到信號的進程的執行,轉而去執行相應的信號處理程序。

  • (1)注冊信號處理函數
#include<signal.h>/*typedefvoid (*sighandler_t)(int); sighandler_t signal(int signum,sighandler_thandler);*/void (*signal(intsignum, void (*handler)(int)))(int); //SIG_IGN && SIG_DFLint sigaction(int signum, const struct sigaction*act,struct sigaction *oldact); 復制代碼
  • (2)發送信號
#include<signal.h>intkill(pid_t pid,int sig); //#include<sys/types.h> intraise(intsig); //kill(getpid(),sig);unsignedint alarm(unsigned int seconds); //(#include<unistd.h>) seconds秒后,向進程本身發送SIGALRM信號。 復制代碼
  • (3)信號集 信號集被定義為:
typedef struct {unsigned long sig[_NSIG_WORDS];}sigset_t;* intsigaddset(sigset_t *set,int sig);* intsigemptyset(sigset_t *set); 復制代碼

2、管道(Pipe)

管道用來連接不同進程之間的數據流。

  • (1)在兩個程序之間傳遞數據的最簡單的方法是使用popen()和pclose()函數:
#include<stdio.h>FILE *popen(const char *command,const char *open_mode);int pclose(FILE *stream); 復制代碼

popen()函數首先調用一個shell,然后把command作為參數傳遞給shell。這樣每次調用popen()函數都需要啟動兩個進程;但是由于在Linux中,所有的參數擴展(parameter expansion)都是由shell執行的,這樣command中包含的所有參數擴展都可以在command程序啟動之前完成。

  • (2)pipe()函數:
int pipe(int pipefd[2]); 復制代碼

popen()函數只能返回一個管道描述符,并且返回的是文件流(filestream),可以使用函數fread()和fwrite()來訪問。pipe()函數可以返回兩個管道描述符:pipefd[0]和pipefd[1],任何寫入pipefd[1]的數據都可以從pipefd[0]讀回;pipe()函數返回的是文件描述符(file descriptor),因此只能使用底層的read()和write()系統調用來訪問。pipe()函數通常用來實現父子進程之間的通信。

  • (3)命名管道:FIFO
intmkfifo(const char *fifo_name, mode_t mode); 復制代碼

前面兩種管道只能用在相關的程序之間,使用命名管道可以解決這個問題。在使用open()打開FIFO時,mode中不能包含O_RDWR。mode最常用的是O_RDONLY,O_WRONLY與O_NONBLOCK的組合。O_NONBLOCK影響了read()和write()在FIFO上的執行方式。

3、信號量(Semaphores)

System V的信號量集表示的是一個或多個信號量的集合。內核為每個信號量集維護一個semid_ds數據結構,而信號量集中的每個信號量使用一個無名結構體表示,這個結構體至少包含以下成員:

struct{unsigned short semval;//信號量值,總是>=0pid_t sempid; //上一次操作的pid…}; 復制代碼
  • (1)創建或訪問信號量
intsemget(key_t key,int nsems,int flag); 復制代碼

nsems指定信號量集中信號量的個數,如果只是獲取信號量集的標識符(而非新建),那么nsems可以為0。flag的低9位作為信號量的訪問權限位,類似于文件的訪問權限;如果flag中同時指定了IPC_CREAT和IPC_EXCL,那么如果key已與現存IPC對象想關聯的話,函數將會返回EEXIST錯誤。例如,flag可以為IPC_CREAT|0666。

  • (2)控制信號量集
int semctl(intsemid,int semnum,int cmd,union semun arg); 復制代碼

對semid信號量集合執行cmd操作;cmd常用的兩個值是:SETVAL初始化第semnum個信號量的值為arg.val;IPC_RMID刪除信號量。

  • (3)對一個或多個信號量進行操作
int semop(intsemid,struct sembuf *sops,unsigned nsops);struct sembuf{unsignedshort sem_num; //信號量索引short sem_op; //對信號量進行的操作,常用的兩個值為-1和+1,分別代表P、V操作short sem_flag; //比較重要的值是SEM_UNDO:當進程結束時,相應的操作將被取消;同時,如果進程結束時沒有釋放資源的話,系統會自動釋放}; 復制代碼

4、共享內存

共享內存允許兩個或多個進程共享一定的存儲區,因為不需要拷貝數據,所以這是最快的一種IPC。

  • (1)創建或訪問共享內存
intshmget(key_t key,size_t size,int shmflg); 復制代碼
  • (2)附加共享內存到進程的地址空間
void*shmat(int shmid,const void *shmaddr,int shmflg);// shmaddr通常為NULL,由系統選擇共享內存附加的地址;shmflg可以為SHM_RDONLY 復制代碼
  • (3)從進程的地址空間分離共享內存
* intshmdt(const void *shmaddr); //shmaddr是shmat()函數的返回值 復制代碼
  • (4)控制共享內存
intshmctl(int shmid,int cmd,struct shmid_ds *buf);struct shmid_ds{structipc_perm shm_perm;…}; 復制代碼

cmd的常用取值有:
(a)IPC_STAT獲取當前共享內存的shmid_ds結構并保存在buf中
(b)IPC_SET使用buf中的值設置當前共享內存的shmid_ds結構
(c)IPC_RMID刪除當前共享內存

5、消息隊列

消息隊列保存在內核中,是一個由消息組成的鏈表。

  • (1)創建或訪問消息隊列
int msgget(key_t key,int msgflg); 復制代碼
  • (2)操作消息隊列
intmsgsnd(int msqid,const void *msg,size_t nbytes,int msgflg); 復制代碼

msg指向的結構體必須以一個longint成員開頭,作為msgrcv()的消息類型,必須大于0。nbytes指的是msg指向結構體的大小,但不包括longint部分的大小 ssize_t msgrcv(intmsqid,void *msg,size_t nbytes,long msgtype,int msgflg); 如果msgtype是0,就返回消息隊列中的第一個消息;如果是正整數,就返回隊列中的第一個該類型的消息;如果是負數,就返回隊列中具有最小值的第一個消息,并且該最小值要小于等于msgtype的絕對值。

  • (3)控制消息隊列
int msgctl(intmsqid,int cmd,struct msqid_ds *buf);struct msqid_ds{struct ipc_permmsg_perm;…};復制代碼

6、Socket

套接字(Socket)是由Berkeley在BSD系統中引入的一種基于連接的IPC,是對網絡接口(硬件)和網絡協議(軟件)的抽象。它既解決了無名管道只能在相關進程間單向通信的問題,又解決了網絡上不同主機之間無法通信的問題。
??套接字有三個屬性:域(domain)、類型(type)和協議(protocol),對應于不同的域,套接字還有一個地址(address)來作為它的名字。
??域(domain)指定了套接字通信所用到的協議族,最常用的域是AF_INET,代表網絡套接字,底層協議是IP協議。對于網絡套接字,由于服務器端有可能會提供多種服務,客戶端需要使用IP端口號來指定特定的服務。AF_UNIX代表本地套接字,使用Unix/Linux文件系統實現。
??IP協議提供了兩種通信手段:流(streams)和數據報(datagrams),對應的套接字類型(type)分別為流式套接字和數據報套接字。流式套接字(SOCK_STREAM)用于提供面向連接、可靠的數據傳輸服務。該服務保證數據能夠實現無差錯、無重復發送,并按順序接收。流式套接字使用TCP協議。數據報套接字(SOCK_DGRAM)提供了一種無連接的服務。該服務并不能保證數據傳輸的可靠性,數據有可能在傳輸過程中丟失或出現數據重復,且無法保證順序地接收到數據。數據報套接字使用UDP協議。
??一種類型的套接字可能可以使用多于一種的協議來實現,套接字的協議(protocol)屬性用于指定一種特定的協議。 ??

  • (1)創建套接字
int socket(int domain,int type,int protocol); 復制代碼

對于SOCK_STREAM和SOCK_DGRAM而言,分別只有一種協議支持這種類型的套接字。因此protocol可以為0,表示默認的協議。

  • (2) 綁定套接字
int bind(int sockfd,const struct sockaddr *addr,socklen_t addrlen);//將無名套接字sockfd與addr綁定(bind) 復制代碼
  • (3)監聽套接字
int listen(int sockfd,int backlog);//backlog限定了等待服務的隊列的最大長度 復制代碼
  • (4)等待接受連接
int accept(int sockfd,struct sockaddr *addr,socklen_t *addrlen); 復制代碼

當客戶端程序嘗試連接sockfd套接字時,accept返回一個新的套接字與客戶端進行通信。如果addr不是NULL,那么客戶端的地址將會保存在addr所指向的結構體中;調用accept()前必須先將addrlen初始化為addr所指向結構體的大小,accept()返回以后,addrlen將會被設置成客戶端套接字地址結構體的實際大小。然后,通過對accept()返回的套接字執行read()和write()操作即可實現與客戶端的簡單的通信。 ??

  • (5)建立連接(客戶端)
int connect(int sockfd,const struct sockaddr *addr,socklen_t addrlen); 復制代碼

connect()在無名套接字sockfd和addr之間建立連接。addr指向的結構體中可以包含服務器的IP地址和端口號等信息。

  • (6)數據傳輸
ssize_t send(int sockfd,const void *buf,size_t len,int flags);ssize_t recv(int sockfd, void *buf, size_t len,int flags); 復制代碼
  • (7)關閉套接字
int close(int fd); 復制代碼
  • (8)主機字節序和網絡字節序的轉換
#include <netinet/in.h>unsigned long int htonl(unsigned long int hostlong); //host to network,longunsigned short int htons(unsigned short int hostshort);unsigned long int ntohl(unsigned long int netlong);unsigned short int ntohs(unsigned short int netshort);// long型函數用來轉換sockaddr_in.in_addr.s_addr; // short型函數用來轉換sockaddr_in.sin_port。 復制代碼

總結

以上是生活随笔為你收集整理的Linux 常见的六大 IPC 通信方式的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。