C语言进程通信消息队列和共享内存(5)

欢迎加入QQ:498903810 一起交流、讨论知识,里面有大佬,也有小白,天下码农一家亲,大家一起讨论进步。

本节所有代码点击获得

消息队列

消息队列:默认发送端将信息放在前一个信息后面,接收消息端可以指定接收哪一个消息。

1、msgget():创建打开一个消息队列

int msgget(key_t key, int msgflg);

key:键值,这个键值就可以创建不同进程的消息队列

参数1:键值;参数二:权限相关

//头文件
#include 
#include 
#include 

//函数原型
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 
#include 

//函数原型
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 
#include 
#include 

//函数原型
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 
#include 

//函数原型
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 
#include 

//函数原型
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 
#include 

//函数原型
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 

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

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

kill

//头文件
#include 
#include 

//函数原型
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

你可能感兴趣的:(C语言,Linux,C/C++开发工程师之路)