1. 程式人生 > >C語言程序通訊訊息佇列和共享記憶體(5)

C語言程序通訊訊息佇列和共享記憶體(5)

歡迎加入QQ:498903810 一起交流、討論知識,裡面有大佬,也有小白,天下碼農一家親,大家一起討論進步。

訊息佇列

訊息佇列:預設傳送端將資訊放在前一個資訊後面,接收訊息端可以指定接收哪一個訊息。

1、msgget():建立開啟一個訊息佇列

int msgget(key_t key, int msgflg);

key:鍵值,這個鍵值就可以建立不同程序的訊息佇列

引數1:鍵值;引數二:許可權相關

//標頭檔案
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

//函式原型
int msgget(key_t key, int msgflg);//key鍵值

//描述
The  msgget() system call returns the System V message queue identifier associated with
the value of the key argument. A new message queue is created if key has the value IPC_PRIVATE or key isn't IPC_PRIVATE, no message queue with the given key key exists, and IPC_CREAT is specified in msgflg. If msgflg specifies both IPC_CREAT and IPC_EXCL and a message queue already exists for
key, then msgget() fails with errno set to EEXIST. (This is analogous to the effect of the combination O_CREAT | O_EXCL for open(2).) ... ... //返回值 If successful, the return value will be the message queue identifier (anonnegative integer), otherwise -1 with errno indicating the error.

2、 ftok()
:獲取特定的鍵值

key_t ftok(const char *pathname, int proj_id);

引數1:路徑;引數2:至少是一個char的字元(非零)。

//標頭檔案
#include <sys/types.h>
#include <sys/ipc.h>

//函式原型
key_t ftok(const char *pathname, int proj_id);

//描述
The ftok() function uses the identity of the file named  by  the  given pathname  (which  must  refer  to an existing, accessible file) and the least significant 8 bits of proj_id (which must be nonzero) to generate a  key_t  type  System  V  IPC  key,  suitable  for use with msgget(2), semget(2), or shmget(2).

//返回值
On  success,  the  generated key_t value is returned.  On failure -1 is returned, with errno indicating the error as  for  the  stat(2)  system call.

3、msgsnd()msgrcv():傳送訊息和接收訊息

msgsnd():傳送訊息到訊息佇列

int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);

引數1:訊息佇列的ID號;引數2:訊息傳送的資訊結構體;引數3:大小,結構體裡面陣列的大小;引數4:阻塞(0)或者非阻塞(IPC_NOWAIT)

//標頭檔案
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

//函式原型
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);

//結構體
struct msgbuf {
  long mtype;       /* message type, must be > 0 *///訊息型別
  char mtext[1];    /* message data */
};
The  mtext  field is an array (or other structure) whose size is speci‐ fied by msgsz, a nonnegative integer value.  Messages  of  zero  length (i.e.,  no  mtext  field)  are  permitted.  The mtype field must have a strictly positive integer value.  This value can be used by the receiving  process  for  message  selection  (see the description of msgrcv() below).


The msgflg argument is a bit mask constructed by ORing together zero or more of the following flags:

0//不寫任何東西表示阻塞

IPC_NOWAIT//不阻塞
Return immediately if no message of the requested type is in the queue.  The system call fails with errno set to ENOMSG.

MSG_EXCEPT
Used with msgtyp greater than 0 to read the first message in the queue with message type that differs from msgtyp.

MSG_NOERROR
To truncate the message text if longer than msgsz bytes.

msgrcv()接收訊息

ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);

引數1:訊息佇列的ID號;引數2:訊息傳送的資訊結構體;引數3:大小,結構體裡面陣列的大小;引數4:阻塞(0)或者非阻塞(IPC_NOWAIT);引數5:選擇接收的資訊。

有用的資訊將來會放在msgp這個結構體的元素(陣列)裡。

msgflag也是阻塞讀取,意思就是有訊息就一直讀,沒訊息就阻塞。

msgtyp,選擇0,就是預設先讀取第一個訊息。

The msgrcv() system call removes a message from the queue specified  by msqid and places it in the buffer pointed to by msgp.

The  argument  msgsz specifies the maximum size in bytes for the member mtext of the structure pointed to by the msgp argument.  If the message text  has  length  greater  than  msgsz,  then  the behavior depends on whether MSG_NOERROR is specified in msgflg.  If MSG_NOERROR  is  speci‐ fied,  then  the message text will be truncated (and the truncated part will be lost); if MSG_NOERROR is not specified, then the message  isn't removed  from  the  queue  and  the system call fails returning -1 with
errno set to E2BIG.

The argument msgtyp specifies the type of message requested as follows:

//只讀第一個訊息
* If msgtyp is 0, then the first message in the queue is read.

* If msgtyp is greater than 0, then the first message in the  queue  of type  msgtyp  is  read, unless MSG_EXCEPT was specified in msgflg, in which case the first message in the queue of type not equal to msgtyp will be read.

* If  msgtyp  is  less than 0, then the first message in the queue with the lowest type less than or equal to the absolute  value  of  msgtyp will be read.

4、msgctl()結束佇列

訊息佇列是在核心中維護的,用完之後,自己清理。

int msgctl(int msqid, int cmd, struct msqid_ds *buf);

引數1:qid;引數2:IPC_RMID;引數3:NULL(不關心詳細的佇列特性:傳送接收時間)

//標頭檔案
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

//函式原型
int msgctl(int msqid, int cmd, struct msqid_ds *buf);

//cmd引數
IPC_RMID
Immediately  remove  the  message  queue,  awakening all waiting reader and writer processes (with an error return and errno  set to EIDRM).  The calling process must have appropriate privileges or its effective user ID must be either that of the  creator  or owner of the message queue.

共享記憶體

共享記憶體:從真實的物理空間找一段記憶體,對映到虛擬記憶體。在不同程序之間的對映記憶體都以為這段記憶體是自己,這就牽扯到同步。

1、shmget()得到記憶體

shmget():從實體地址得到確定大小的記憶體

int shmget(key_t key, size_t size, int shmflg);

引數1:特殊鍵值;引數2:獲取記憶體大小(位元組);引數3:對申請記憶體的許可權;

PS:ipcs -m //專門檢視共享記憶體的詳細資訊。

//標頭檔案
#include <sys/ipc.h>
#include <sys/shm.h>

//函式原型
int shmget(key_t key, size_t size, int shmflg);

//返回值
On  success,  a valid shared memory identifier is returned.  On errir, -1 is returned, and errno is set to indicate the error.

2、shmctl()刪除共享記憶體

//標頭檔案
#include <sys/ipc.h>
#include <sys/shm.h>

//函式原型
int shmctl(int shmid, int cmd, struct shmid_ds *buf);

3、shmmat()shmdt()建立共享和斷開連結

shmmat()

void *shmat(int shmid, const void *shmaddr, int shmflg);

引數1:shmget()的返回值;引數2:shumaddr = NULL,表示作業系統自動分配一個未使用而且安全的地址;引數3:選擇IPC_RDONLY只讀模式,猜測0是可讀可寫

shmdt()斷開共享記憶體和所處程序之間的對映關係

int shmdt(const void *shmaddr);

引數1:裡面放的是,所處程序中對映過去的有效、合法地址、未使用地址。

//標頭檔案
#include <sys/types.h>
#include <sys/shm.h>

//函式原型
void *shmat(int shmid, const void *shmaddr, int shmflg);
int shmdt(const void *shmaddr);

//shmat()描述
shmat()  attaches  the  System  V  shared memory segment identified by shmid to the address space of  the  calling  process.   The  attaching address is specified by shmaddr with one of the following criteria:
If  shmaddr is NULL, the system chooses a suitable (unused) address at which to attach the segment.
... ...

//引數3
If  SHM_RDONLY  is  specified  in  shmflg, the segment is attached for reading and the process must have read  permission  for  the  segment. Otherwise  the  segment is attached for read and write and the process must have read and write permission for  the  segment.   There  is  no notion of a write-only shared memory segment.
//shmdt()描述

shmdt()  detaches  the  shared  memory  segment located at the address
specified by shmaddr from the address space of  the  calling  process.
The  to-be-detached  segment  must  be currently attached with shmaddr
equal to the value returned by the attaching shmat() call.

On a successful shmdt() call the system updates  the  members  of  the
shmid_ds  structure  associated with the shared memory segment as fol‐
lows:

shm_dtime is set to the current time.

shm_lpid is set to the process-ID of the calling process.

shm_nattch is decremented by one.  If it becomes 0 and the seg‐
ment is marked for deletion, the segment is deleted.

訊號

訊號:是一種非同步通訊方式,通訊內容有限制。

訊號都是事先編好的一系列int資料。

訊號的產生:

(1)、硬體產生:滑鼠點選

(2)、滿足某種軟體需求訊號產生

(3)、硬體異常發生訊號

(4)、kill - 9產生一個訊號

訊號的處理方式:給誰發的誰處理

(1)、預設處理

(2)、捕獲處理(訊號綁定了一個函式)

(3)、忽略處理

常見訊號:路徑:/usr/include/bits/signum.h

(1)、SIGINT 2 //就是我們平時用到的ctrl + c,打斷死迴圈

(2)、SIGABRT 6 //程式的異常終止

(3)、SIGKILL 9 //殺死一個程序(終極方法)

(4)、SIGSEGV 11 //訪問非法記憶體

(5)、SIGALRM 14 //鬧鐘訊號

(6)、SIGCHLD 17 //子程序結束時傳送的訊號

(7)、SIGSTOP 19 //暫停一個程序

(8)、SIGCONT 18//喚醒一個SIGSTOP暫停的程序

raise()安裝訊號

raise()傳送一個訊號給當前程序

//標頭檔案
#include <signal.h>

//函式原型
int raise(int sig);

//返回值
raise() returns 0 on success, and nonzero for failure.

kill

//標頭檔案
#include <sys/types.h>
#include <signal.h>

//函式原型
int kill(pid_t pid, int sig);

Feature Test Macro Requirements for glibc (see feature_test_macros(7)):

kill(): _POSIX_C_SOURCE >= 1 || _XOPEN_SOURCE || _POSIX_SOURCE