進程間通信 (IPC) 方法總結(三)

進程間通信 (IPC) 方法總結(三)

信號量(SEMAPHORE)

信號量是一個計數器,用于多進程對共享數據的訪問,信號量的意圖在于進程間同步。
為了獲得共享資源,進程需要執行下列操作:

  1. 創建一個信號量:這要求調用者指定初始值,對于二值信號量來說,它通常是1,也可是0。
  2. 等待一個信號量:該操作會測試這個信號量的值,如果小于0,就阻塞。也稱為P操作。
  3. 掛出一個信號量:該操作將信號量的值加1,也稱為V操作。

為了正確地實現信號量,信號量值的測試及減1操作應當是原子操作。為此,信號量通常是在內核中實現的。Linux環境中,有三種類型:Posix(可移植性操作系統接口)有名信號量(使用Posix IPC名字標識)、Posix基于內存的信號量(存放在共享內存區中)、System V信號量(在內核中維護)。這三種信號量都可用于進程間或線程間的同步。

Posix有名信號量

webp

Posix基于內存的信號量

webp

System V信號量

webp

信號量與普通整型變量的區別

  1. 信號量是非負整型變量,除了初始化之外,它只能通過兩個標準原子操作:wait(semap) , signal(semap) ; 來進行訪問;
  2. 操作也被成為PV原語(P來源于荷蘭語proberen"測試",V來源于荷蘭語verhogen"增加",P表示通過的意思,V表示釋放的意思),而普通整型變量則可以在任何語句塊中被訪問;

    信號量與互斥量之間的區別

  3. 互斥量用于線程的互斥,信號量用于線程的同步。這是互斥量和信號量的根本區別,也就是互斥和同步之間的區別。

    互斥:是指某一資源同時只允許一個訪問者對其進行訪問,具有唯一性和排它性。但互斥無法限制訪問者對資源的訪問順序,即訪問是無序的。

    同步:是指在互斥的基礎上(大多數情況),通過其它機制實現訪問者對資源的有序訪問。

    在大多數情況下,同步已經實現了互斥,特別是所有寫入資源的情況必定是互斥的。少數情況是指可以允許多個訪問者同時訪問資源

  4. 互斥量值只能為0/1,信號量值可以為非負整數。

    也就是說,一個互斥量只能用于一個資源的互斥訪問,它不能實現多個資源的多線程互斥問題。信號量可以實現多個同類資源的多線程互斥和同步。當信號量為單值信號量是,也可以完成一個資源的互斥訪問。

  5. 互斥量的加鎖和解鎖必須由同一線程分別對應使用,信號量可以由一個線程釋放,另一個線程得到。

套接字(SOCKET)

套接字是一種通信機制,憑借這種機制,客戶/服務器(即要進行通信的進程)系統的開發工作既可以在本地單機上進行,也可以跨網絡進行。也就是說它可以讓不在同一臺計算機但通過網絡連接計算機上的進程進行通信。
套接字示意圖

套接字是支持TCP/IP的網絡通信的基本操作單元,可以看做是不同主機之間的進程進行雙向通信的端點,簡單的說就是通信的兩方的一種約定,用套接字中的相關函數來完成通信過程。

套接字特性

套接字的特性由3個屬性確定,它們分別是:域、端口號、協議類型。

套接字的域

它指定套接字通信中使用的網絡介質,最常見的套接字域有兩種:

  1. AF_INET,它指的是Internet網絡。當客戶使用套接字進行跨網絡的連接時,它就需要用到服務器計算機的IP地址和端口來指定一臺聯網機器上的某個特定服務,所以在使用socket作為通信的終點,服務器應用程序必須在開始通信之前綁定一個端口,服務器在指定的端口等待客戶的連接。
  2. AF_UNIX,表示UNIX文件系統,它就是文件輸入/輸出,而它的地址就是文件名。

    套接字的端口號

    每一個基于TCP/IP網絡通訊的程序(進程)都被賦予了唯一的端口和端口號,端口是一個信息緩沖區,用于保留Socket中的輸入/輸出信息,端口號是一個16位無符號整數,范圍是0-65535,以區別主機上的每一個程序(端口號就像房屋中的房間號),低于256的端口號保留給標準應用程序,比如pop3的端口號就是110,每一個套接字都組合進了IP地址、端口,這樣形成的整體就可以區別每一個套接字。

    套接字協議類型
  3. 流套接字
    流套接字在域中通過TCP/IP連接實現,同時也是AF_UNIX中常用的套接字類型。流套接字提供的是一個有序、可靠、雙向字節流的連接,因此發送的數據可以確保不會丟失、重復或亂序到達,而且它還有一定的出錯后重新發送的機制。
  4. 數據報套接字
    它不需要建立連接和維持一個連接,它們在域中通常是通過UDP/IP協議實現的。它對可以發送的數據的長度有限制,數據報作為一個單獨的網絡消息被傳輸,它可能會丟失、復制或錯亂到達,UDP不是一個可靠的協議,但是它的速度比較高,因為它并一需要總是要建立和維持一個連接。
  5. 原始套接字
    原始套接字允許對較低層次的協議直接訪問,比如IP、 ICMP協議,它常用于檢驗新的協議實現,或者訪問現有服務中配置的新設備,因為RAW SOCKET可以自如地控制Windows下的多種協議,能夠對網絡底層的傳輸機制進行控制,所以可以應用原始套接字來操縱網絡層和傳輸層應用。比如,我們可以通過RAW SOCKET來接收發向本機的ICMP、IGMP協議包,或者接收TCP/IP棧不能夠處理的IP包,也可以用來發送一些自定包頭或自定協議的IP包。網絡監聽技術很大程度上依賴于SOCKET_RAW。

原始套接字與標準套接字的區別

原始套接字可以讀寫內核沒有處理的IP數據包,而流套接字只能讀取TCP協議的數據,數據報套接字只能讀取UDP協議的數據。因此,如果要訪問其他協議發送數據必須使用原始套接字。

套接字通信的建立

套接字通信的建立

  • 服務端
    1. 首先服務器應用程序用系統調用socket來創建一個套接字,它是系統分配給該服務器進程的類似文件描述符的資源,它不能與其他的進程共享。(socket)
    2. 服務器進程會給套接字起個名字,我們使用系統調用bind來給套接字命名。然后服務器進程就開始等待客戶連接到這個套接字。(bind)
    3. 系統調用listen來創建一個隊列并將其用于存放來自客戶的進入連接。(listen)
    4. 服務器通過系統調用accept來接受客戶的連接。它會創建一個與原有的命名套接不同的新套接字,這個套接字只用于與這個特定客戶端進行通信,而命名套接字(即原先的套接字)則被保留下來繼續處理來自其他客戶的連接(建立客戶端和服務端的用于通信的流,進行通信)。(accept--read/write)
  • 客戶端
    1. 客戶應用程序首先調用socket來創建一個未命名的套接字。(socket)
    2. 將服務器的命名套接字作為一個地址來調用connect與服務器建立連接。(connect)
    3. 一旦連接建立,我們就可以像使用底層的文件描述符那樣用套接字來實現雙向數據的通信(通過流進行數據傳輸)(read/write)

eg.

服務端代碼

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h> //socket listen bind
#include <sys/socket.h>//socket listen bind 
#include <unistd.h>//unlink
#include <sys/un.h>//struct sockaddr_unint main()  
{  /* delete the socket file */  unlink("server_socket");  /* create a socket */  int server_sockfd = socket(AF_UNIX, SOCK_STREAM, 0);  struct sockaddr_un server_addr;  server_addr.sun_family = AF_UNIX;  strcpy(server_addr.sun_path, "server_socket");  /* bind with the local file */  bind(server_sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr));  /* listen */  listen(server_sockfd, 5);  char ch;  int client_sockfd;  struct sockaddr_un client_addr;  socklen_t len = sizeof(client_addr);  while(1)  {  printf("server waiting:\n");  /* accept a connection */  client_sockfd = accept(server_sockfd, (struct sockaddr *)&client_addr, &len);  /* exchange data */  read(client_sockfd, &ch, 1);  printf("get char from client: %c\n", ch);  ++ch;  write(client_sockfd, &ch, 1);  /* close the socket */  close(client_sockfd);  }  return 0;  
}  

客戶端代碼

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h> //socket listen bind
#include <sys/socket.h>//socket listen bind 
#include <unistd.h>//unlink
#include <sys/un.h>//struct sockaddr_un  int main()  
{  /* create a socket */  int sockfd = socket(AF_UNIX, SOCK_STREAM, 0);  struct sockaddr_un address;  address.sun_family = AF_UNIX;  strcpy(address.sun_path, "server_socket");  /* connect to the server */  int result = connect(sockfd, (struct sockaddr *)&address, sizeof(address));  if(result == -1)  {  perror("connect failed: ");  exit(1);  }  /* exchange data */  char ch = 'A';  write(sockfd, &ch, 1);  read(sockfd, &ch, 1);  printf("get char from server: %c\n", ch);  /* close the socket */  close(sockfd);  return 0;  
}  

如果我們首先運行tcp_client,會提示沒有這個文件:

1335595740_7456.png

因為我們是以AF_UNIX方式進行通信的,這種方式是通過文件來將服務器和客戶端連接起來的,因此我們應該先運行tcp_server,創建這個文件,默認情況下,這個文件會創建在當前目錄下,并且第一個s表示它是一個socket文件:

1335595745_9357.png

程序運行的結果如下圖:

1335595904_8794.png


參考文章:

  1. 進程間通信IPC (InterProcess Communication)

  2. 進程間通信--管道

  3. UNIX/Linux進程間通信IPC系列(四)消息隊列

  4. Linux進程間通信(四) - 共享內存

  5. 本地socket通訊

轉載于:https://www.cnblogs.com/joker-wz/p/11013086.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/393289.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/393289.shtml
英文地址,請注明出處:http://en.pswp.cn/news/393289.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

leetcode1277. 統計全為 1 的正方形子矩陣(dp)

給你一個 m * n 的矩陣&#xff0c;矩陣中的元素不是 0 就是 1&#xff0c;請你統計并返回其中完全由 1 組成的 正方形 子矩陣的個數。示例 1&#xff1a;輸入&#xff1a;matrix [[0,1,1,1],[1,1,1,1],[0,1,1,1] ] 輸出&#xff1a;15 解釋&#xff1a; 邊長為 1 的正方形有…

實現離線加域---Windows2008 R2 新功能系列之八

我們都知道&#xff0c;部署活動目錄&#xff0c;無非搭建一臺或多臺DC&#xff0c;然后把其它的客戶端計算機或成員服務器全部加入域&#xff0c;但在windows2008SP2以前&#xff0c;客戶端加入域時&#xff0c;DC必須在線&#xff0c;而從2008R2開始我們已經可以做到讓客戶端…

【bzoj1263】[SCOI2006]整數劃分 高精度

題目描述 從文件中讀入一個正整數n&#xff08;10≤n≤31000&#xff09;。要求將n寫成若干個正整數之和&#xff0c;并且使這些正整數的乘積最大。 例如&#xff0c;n13&#xff0c;則當n表示為4333&#xff08;或22333&#xff09;時&#xff0c;乘積108為最大。 輸入 只有一…

rails i18n模型_Rails國際化的完整指南(i18n)

rails i18n模型by Anastasia由Anastasia Rails國際化的完整指南(i18n) (The Complete Guide to Rails Internationalization (i18n)) In this article you are going to learn how to translate your Rails application into multiple languages, work with translations, loc…

分表后需要注意的二三事

前言 本篇是上一篇《一次分表踩坑實踐的探討》&#xff0c;所以還沒看過的朋友建議先看上文。 還是先來簡單回顧下上次提到了哪些內容&#xff1a; 分表策略&#xff1a;哈希、時間歸檔等。分表字段的選擇。數據遷移方案。而本篇文章的背景是在我們上線這段時間遇到的一些問題并…

DNS 原理

阮老師的作品&#xff0c;非常精彩&#xff0c;轉載&#xff01; DNS 是互聯網核心協議之一。不管是上網瀏覽&#xff0c;還是編程開發&#xff0c;都需要了解一點它的知識。 本文詳細介紹DNS的原理&#xff0c;以及如何運用工具軟件觀察它的運作。我的目標是&#xff0c;讀完此…

leetcode1169. 查詢無效交易

如果出現下述兩種情況&#xff0c;交易 可能無效&#xff1a; 交易金額超過 1000 或者&#xff0c;它和另一個城市中同名的另一筆交易相隔不超過 60 分鐘&#xff08;包含 60 分鐘整&#xff09; 每個交易字符串 transactions[i] 由一些用逗號分隔的值組成&#xff0c;這些值分…

銷售員/學員/講師系統

前言: 今晚寫一篇關于學員/講師/銷售員CRM系統。這個小項目是27號開始做的&#xff0c;大概搞了一星期不到。我把一些知識點總結下&#xff0c;還寫下當時克服的BUG。 Django練習小項目&#xff1a;學員管理系統設計開發 帶著項目需求學習是最有趣和效率最高的&#xff0c;今天…

Linux內核啟動

1 內核編譯 解壓縮&#xff1a;tar xjf linux-2.6.22.6.tar.bz2打補丁&#xff1a; path -p1 < ../linux-2.6.22.6_jz2440.patch(其中p1是忽略補丁文件中的一級目錄)配置&#xff1a; 方法一&#xff1a;使用make menuconfig逐項配置方法二&#xff1a;使用默認配置&#xf…

node.js使用手冊_權威的Node.js手冊

node.js使用手冊Developer and freeCodeCamp camper Flavio Copes has published his entire Node.js Handbook online for free - both on freeCodeCamps Medium publication and as a .pdf file. You can read it here.開發人員和freeCodeCamp營員Flavio Copes在freeCodeCamp…

自動化運維之saltstack(二)states深入理解

深入了解SLS的可以參考這篇博文&#xff1a;http://www.ituring.com.cn/article/42238 個人覺得這篇文章翻譯的不錯&#xff0c;所以轉載過來。 Salt Sates 眾多強大而有力的涉及都是建立在簡單的原則之上。Salt SLS系統也是努力想K.I.S.S看齊。&#xff08;Keep It Stupidly …

java里面的 |運算符_Java 中 | ^ 運算符的簡單使用

背景今天碰到了代碼中的按位與運算&#xff0c;復習一下&#xff0c;先列一個各個進制數據表。順便復習一下十進制轉二進制的計算方式&#xff1a;接下來解釋下這三個運算符&#xff1a;&  按位與&#xff0c;都轉為二進制的情況下&#xff0c;同為1則為1&#xff0c;否則…

leetcode915. 分割數組

給定一個數組 A&#xff0c;將其劃分為兩個不相交&#xff08;沒有公共元素&#xff09;的連續子數組 left 和 right&#xff0c; 使得&#xff1a; left 中的每個元素都小于或等于 right 中的每個元素。 left 和 right 都是非空的。 left 要盡可能小。 在完成這樣的分組后返回…

徹底理解正向代理、反向代理、透明代理

套用古龍武俠小說套路來說&#xff0c;代理服務技術是一門很古老的技術&#xff0c;是在互聯網早期出現就使用的技術。一般實現代理技術的方式就是在服務器上安裝代理服務軟件&#xff0c;讓其成為一個代理服務器&#xff0c;從而實現代理技術。常用的代理技術分為正向代理、反…

使用showMessageDialog顯示消息框

-----------------siwuxie095 工程名&#xff1a;TestJOptionPane 包名&#xff1a;com.siwuxie095.showdialog 類名&#xff1a;TestMessageDialog.java 工程結構目錄如下&#xff1a; 代碼&#xff1a; package com.siwuxie095.showdialog; import java.awt.BorderLayout;…

將Javascript帶到邊緣設備

Smart devices today are very similar to labour-saving gadgets a generation ago: Where previously everything got a power cord, now everything gets a chip. 如今的智能設備與上一代的省力小工具非常相似&#xff1a;以前所有設備都配有電源線&#xff0c;而現在所有設…

java 泛型 父子_使用通配符和泛型:完成父子類關系的List對象的類型匹配

泛型和通配符使用泛型和通配符都可以讓一個方法所表示的算法邏輯適應多種類型。Java中具備繼承關系的類A、B(A extends B)它們的集合List和List之間是沒有繼承關系的&#xff0c;可以使用泛型或通配符來讓一個方法支持同時接受List和List。代碼場景這里分別定義類Animal、Dog和…

重定向描述符

文件描符 縮寫 描述 0 STDIN 標準輸入 1 STDOUT 標準輸出 2 STDERR 標準錯誤 1、重定向錯誤和數據 1234[rootlogicserver tmp]# ls -al data1 haha 2> qingyun.txt 1&g…

NodeJS學習筆記(一)——搭建開發框架Express,實現Web網站登錄驗證

目錄 開發環境  1、建立工程  2、目錄結構  3、Express配置文件  4、Ejs模板  5、安裝常用庫及頁面分離  6、路由  7、session  8、頁面訪問控制及提示JS是腳本語言&#xff0c;腳本語言都需要一個解析器才能運行。對于寫在HTML頁面里 的JS&#xff0c;瀏覽器充…

LeetCode-208 Implement Trie (Prefix Tree)

題目描述 Implement a trie with insert, search, and startsWith methods. 題目大意 實現對一棵樹的插入、搜索以及前序查找操作。 &#xff08;樹的每個節點代表一個小寫字母&#xff0c;從根節點到葉節點代表一個完整的單詞&#xff09; 示例 E Trie trie new Trie();trie.…