Linux學習之路(17)

2021-09-05 10:26:12 字數 4830 閱讀 5699

程序間通訊

一:管道通訊

無名管道:無名管道由pipe()函式建立:

int pipe(int filedis[2]);

當乙個管道建立時,它會建立兩個檔案描述符:

filedis[0]用於讀管道,filedis[1]用於寫管道。

命名管道命名管道建立:#include

#include

int mkfifo(const char *pathname, mode_t mode);

pathname: fifo檔名

mode:屬性(同檔案操作)

一旦建立了乙個fifo,就可用open開啟它,一般的檔案訪問函式(close、read、write等)都可用於fifo。

命名管道操作:當開啟fifo時,非阻塞標識(o_nonblock)將對以後的讀寫產生影響:

1、沒有使用o_nonblock:訪問要求無法滿足時程序將阻塞。如果試圖讀取空的fifo,將導致程序阻塞。

2、使用o_nonblock:訪問要求無法滿足時不阻塞,立刻出錯返回。errno是enxio。

管道關閉:關閉管道只需要將兩個檔案描述符關閉即可,可以使用普通的close函式逐個關閉。

二、共享記憶體

關閉管道只需要將兩個檔案描述符關閉即可,可以使用普通的close函式逐個關閉。

共享記憶體建立:int shmget(key_t key, int size, int shm***)

key:

1、0/ipc_private:當key的取值為ipc_private,則函式shmget()將建立一塊新的共享記憶體;如果key取值為0,而引數shm***中又設定ipc_private這個標誌,則同樣會建立一塊新的共享記憶體。

2、大於0的32位整數:視引數shm***來確定操作。

size:

1、大於0的整數:新建的共享記憶體大小,以位元組為單位0:

2、只獲取共享記憶體時指定為0

shm***:模式標誌引數,使用時需要與ipc物件訪問許可權(如0600)進行|運算來確定共享記憶體的訪問許可權

1、0:取共享記憶體識別符號,若不存在則函式會報錯

2、ipc_creat:當shm***&ipc_creat為真時,如果核心中不存在鍵值與key相等的共享記憶體,則新建乙個共享記憶體;如果存在這樣的共享記憶體,返回此共享記憶體的識別符號

3、ipc_creat|ipc_excl:如果核心中不存在鍵值 與key相等的共享記憶體,則新建乙個共享記憶體;如果存在這樣的共享記憶體則報錯

返回值:如果成功,返回共享記憶體識別符號;如果失敗,返回-1。

對映:void* shmat(int shmid, char *shmaddr, int flag)

引數:第乙個引數,shm_id是由shmget函式返回的共享記憶體標識。

第二個引數,shm_addr指定共享記憶體連線到當前程序中的位址位置,通常為空,表示讓系統來選擇共享記憶體的位址。

第三個引數,shm_***是一組標誌位,通常為0。

解除對映:當乙個程序不再需要共享記憶體時,需要把它從程序位址空間中脫離

int shmdt(char *shmaddr);

引數shmaddr是shmat函式返回的位址指標,呼叫成功時返回0,失敗時返回-1. 

該函式用於將共享記憶體從當前程序中分離。注意,將共享記憶體分離並不是刪除它,只是使該共享記憶體對當前程序不再可用。

共享記憶體控制:int shmctl(int shm_id, int command, struct shmid_ds *buf);  

第乙個引數,shm_id是shmget函式返回的共享記憶體識別符號。

第二個引數,command是要採取的操作,它可以取下面的三個值 :

ipc_stat:把shmid_ds結構中的資料設定為共享記憶體的當前關聯值,即用共享記憶體的當前關聯值覆蓋shmid_ds的值。

ipc_set:如果程序有足夠的許可權,就把共享記憶體的當前關聯值設定為shmid_ds結構中給出的值

ipc_rmid:刪除共享記憶體段

第三個引數,buf是乙個結構指標,它指向共享記憶體模式和訪問許可權的結構。

shmid_ds結構至少包括以下成員:

struct shmid_ds

;三、型號量

1、建立

int semget(key_t key, int num_sems, int sem_flags);  

第乙個引數key是整數值(唯一非零),不相關的程序可以通過它訪問乙個訊號量,它代表程式可能要使用的某個資源,程式對所有訊號量的訪問都是間接的,程式先通過呼叫semget函式並提供乙個鍵,再由系統生成乙個相應的訊號識別符號(semget函式的返回值),只有semget函式才直接使用訊號量鍵,所有其他的訊號量函式使用由semget函式返回的訊號量識別符號。如果多個程式使用相同的key值,key將負責協調工作。

第二個引數num_sems指定需要的訊號量數目,它的值幾乎總是1。

第三個引數sem_flags是一組標誌,當想要當訊號量不存在時建立乙個新的訊號量,可以和值ipc_creat做按位或操作。設定了ipc_creat標誌後,即使給出的鍵是乙個已有訊號量的鍵,也不會產生錯誤。而ipc_creat | ipc_excl則可以建立乙個新的,唯一的訊號量,如果訊號量已存在,返回乙個錯誤。

semget函式成功返回乙個相應訊號識別符號(非零),失敗返回-1.

2、操作

它的作用是改變訊號量的值:

int semop(int sem_id, struct sembuf *sem_opa, size_t num_sem_ops);  

第乙個引數 sem_id是由semget返回的訊號量識別符號,

第二個引數 sembuf結構的定義如下: 

struct sembuf;

第三個引數 nsops:訊號操作結構的數量,恆大於或等於1

3、控制

該函式用來直接控制訊號量資訊:

int semctl(int sem_id, int sem_num, int command, ...);  

如果有第四個引數,它通常是乙個union semum結構,定義如下:

union semun; 

第乙個引數是訊號量集ipc識別符號。

第二個引數是操作訊號在訊號集中的編號,第乙個訊號的編號是0

第三個引數 command通常是下面兩個值中的其中乙個

setval:用來把訊號量初始化為乙個已知的值。p 這個值通過union semun中的val成員設定,其作用是在訊號量第一次使用前對它進行設定。

ipc_rmid:用於刪除乙個已經無需繼續使用的訊號量識別符號。

四、訊息佇列

1、開啟/建立

#include

#include

#include

int msgget(key_t key, int msg***)

key: 鍵值,由ftok獲得

msg***:標誌位

返回值:與鍵值key相對應的訊息佇列的描述符。

msg***取值:

ipc_creat

建立新的訊息佇列

ipc_excl

與ipc_creat一同使用,表示如果要建立的訊息佇列已經存在,則返回錯誤。

ipc_nowait

讀寫訊息佇列要求無法得到滿足時,不阻塞。

在以下兩種情況下,將建立乙個新的訊息佇列:

如果沒有與鍵值key相對應的訊息佇列,並且msg***中包含了ipc_creat標誌位。

key引數為ipc_private

2、傳送訊息

#include

#include

#include

int msgsnd(int msqid, struct msgbuf * msgp, int msgsz, int msg***)

功能:向訊息佇列中傳送一條訊息

msqid:訊息佇列描述符

msgp:訊息佇列指標,指向存放訊息的結構

msgsz:訊息資料長度

msg***:傳送標誌,有意義的msg***標誌為ipc_nowait,指明在訊息佇列沒有足夠空間容納要傳送的訊息時,msgsnd是否等待

訊息格式:

struct msgbuf

3、接收訊息

#include

#include

#include

int msgrcv(int msqid, struct msgbuf* msgp, int msgsz, long msgtp, int msg***)

功能:從msqid代表的訊息佇列中讀取乙個msgtyp型別的訊息,並把訊息儲存在msgp指向的msgbuf結構中。在成功的讀取了一條訊息以後,佇列中的這條訊息將被刪除。 

4、佇列控制

int msgctl(int msgid, int command, struct msgid_ds *buf);  

command是將要採取的動作,它可以取3個值,

ipc_stat:把msgid_ds結構中的資料設定為訊息佇列的當前關聯值,即用訊息佇列的當前關聯值覆蓋msgid_ds的值。

ipc_set:如果程序有足夠的許可權,就把訊息列隊的當前關聯值設定為msgid_ds結構中給出的值

ipc_rmid:刪除訊息佇列

buf是指向msgid_ds結構的指標,它指向訊息佇列模式和訪問許可權的結構。msgid_ds結構至少包括以下成員:

struct msgid_ds  

;  成功時返回0,失敗時返回-1.

五、訊號通訊

kill

signal

alarm

sigaction

同kill -l  可以看訊號種類

python學習之路(17)

sorted 排序也是在程式中經常用到的演算法。無論使用氣泡排序還是快速排序,排序的核心是比較兩個元素的大小。如果是數字,我們可以直接比較,但如果是字串或者兩個dict呢?直接比較數學上的大小是沒有意義的,因此,比較的過程必須通過函式抽象出來。通常規定,對於兩個元素x和y,如果認為x y,則返回 1...

golang學習之路 17陣列的使用

package main import fmt 語法 var 陣列變數名 number type func main 初始化陣列 var r 3 int 3 int fmt.println r 2 q 0 2.定義陣列 var a 3 int println a 0 println a len a ...

Linux學習之路

一直想學習linux,就其原因,一是懂這個的都被認為水平比較高,二是懂這個的工資也不低,這兩點我也是比較看重的。想學linux也不是一件簡單的事,因為用windows的東西太久了,從3.1到95 98 se nt 2000 me xp 2003,直至最新的windows 7 2008等,全算下來,有...