哪有培训网站开发,手机app怎么开发的,梧州自助建站seo,如何做服装的微商城网站概述
消息队列是消息的链表#xff0c;存放在内存中#xff0c;由内核维护
特点 1 、消息队列中的消息是有类型的。 2 、消息队列中的消息是有格式的。 3 、消息队列可以实现消息的随机查询。消息不一定要以先进先出的次序读取#xff0c;编程时可以按消息的类型读取。 …概述
消息队列是消息的链表存放在内存中由内核维护
特点 1 、消息队列中的消息是有类型的。 2 、消息队列中的消息是有格式的。 3 、消息队列可以实现消息的随机查询。消息不一定要以先进先出的次序读取编程时可以按消息的类型读取。 4 、消息队列允许一个或多个进程向它写入或者读取消息。 5 、与无名管道、命名管道一样从消息队列中读出消息消息队列中对应的数据都会被删除。 6 、每个消息队列都有消息队列标识符消息队列的标识符在整个系统中是唯一的。 7 、只有内核重启或人工删除消息队列时该消息队列才会被删除。若不人工删除消息队列消息队列会一直存在于系统中 注意 : 在 ubuntu 某些版本中消息队列限制值如下 : 每个消息内容最多为 8K 字节 每个消息队列容量最多为 16K 字节 系统中消息队列个数最多为 1609 个 系统中消息个数最多为 16384 个 消息队列·操作命令
ipcs -q 获取消息队列信息
ipcrm -q msgid 删除消息队列id为msgid的消息队列
获取key值 概述 System V 提供的进程间通讯机制 (IPC 通信机制 ) 需要一个 key 值 key 值可以是人为指定的也可以通过 ftok 函数获得。 ftok 函数 所需头文件 : #include sys/types.h #include sys/ipc.h 函数 : key_t ftok(const char *pathname, int proj_id) 参数 pathname路径名 , 这个路径必须是存在的而且可以访问的 //~ 家目录 /// 根目录 //./ 当前目录 proj_id项目 ID 非 0 整数 ( 只有低 8 位有效 ) 返回值 成功返回 key 值 失败返回 -1 注意 : 当调用该函数时传入的参数一致获取到的key 值也将相同 多进程通讯时要保证路径名相同,id 也相同 示例 #include stdio.h
#include sys/types.h
#include sys/ipc.h
int main(int argc, char const *argv[])
{
key_t key01 ftok(./,2023);
key_t key02 ftok(./,2023);
key_t key03 ftok(./,2022);
printf(key1%u\n,key01);
printf(key2%u\n,key02);
printf(key3%u\n,key03);
return 0;
} 创建和获取消息队列-msgget函数
作用 创建一个新的或打开一个已经存在的消息队列。不同的进程调用此函数只要用相同的 key 值就能得到同一个消息队列的标识符 函数 所需头文件 #include sys/msg.h 函数 int msgget(key_t key, int msgflg) 参数 key IPC 键值。 msgflg标识函数的行为及消息队列的权限。 msgflg 的取值 IPC_CREAT创建消息队列。 IPC_EXCL检测消息队列是否存在。 位或权限位消息队列位或权限位后可以设置消息队列的访问权限格式和open 函数的 mode_t 一样但可执行权限未使用。 返回值 成功消息队列的标识符(msgid) 失败返回 -1 #include stdio.h
#include sys/types.h
#include sys/ipc.h
int main(int argc, char const *argv[])
{key_t key ftok(./,12);printf(ipc键值是:%d\n,key);int msgid msgget(key,IPC_CREAT |0666);printf(消息队列id:%d\n,msgid);key_t key2 ftok(./,13);int msgid2 msgget(key2,IPC_EXCL);//查看消息队列是否存在printf(消息队列id2:%d\n,msgid2);return 0;
} 消息格式 typedef struct _msg { long mtype ; /* 消息类型 , 必须是第一个成员 , 必须是 long 型 , 就是该消息的 id*/ char mtext [ 100 ]; /* 消息正文 , 用户自定义 */ ... /* 消息的正文可以有多个成员 */ } MSG ; 发送消息-msgsnd函数 作用 : 将新消息添加到消息队列。 函数 所需头文件 : #include sys/msg.h 函数 : int msgsnd(int msqid, const void *msgp,size_t msgsz, int msgflg); 参数 : msqid消息队列的标识符。 msgp待发送消息结构体的地址。 msgsz消息正文的字节数。 msgflg函数的控制属性 0msgsnd 调用阻塞直到条件满足为止。 ( 推荐 ) IPC_NOWAIT: 若消息没有立即发送则调用该函数的进程会立即返回。 返回值 : 成功0 失败-1 。 接收消息-msgrcv 作用 : 从标识符为 msqid 的消息队列中接收一个消息。一旦接收消息成功则消息 在消息队列中被删除。 函数 所需头文件 #include sys/msg.h 函数 : ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,int msgflg); 参数 : msqid:消息队列的标识符代表要从哪个消息列中获取消息。 msgp:存放消息结构体的地址。 msgsz:消息正文的字节数。 msgtyp:消息的类型、可以有以下几种类型 msgtyp0:返回队列中的第一个消息 msgtyp0:返回队列中消息类型为 msgtyp 的消息 msgtyp0:返回队列中消息类型值小于或等于 msgtyp 绝对值的消息 , 如果这种消息有若干个, 则取类型值最小的消息。 注意 若消息队列中有多种类型的消息 ,msgrcv 获取消息的时候按消息类型获取, 不是先进先出的。 在获取某类型消息的时候 , 若队列中有多条此类型的消息 , 则获取最先添加的消息, 即先进先出原则 msgflg: 函数的控制属性 0:msgrcv调用阻塞直到接收消息成功为止。 MSG_NOERROR:若返回的消息字节数比 nbytes 字节数多 , 则消息就会截短到nbytes字节 , 且不通知消息发送进程 IPC_NOWAIT: 调用进程会立即返回。若没有收到消息则立即返回 -1 。 返回值 : 成功返回读取消息的长度 失败返回-1 案例1简单的消息收发 需要 : 张三发出消息类型为 10 与 20 的消息 李四接收消息类型为 10 的消息 王五接收消息类型为 20 的消息 代码 02_zs.c #include stdio.h
#include sys/types.h
#include sys/ipc.h
#include sys/msg.h
#include string.h
typedef struct struct_msg{
long msgType;
char name[20];
char text[128];
}Msg;
int main(int argc, char const *argv[])
{
//获取key值
key_t key ftok(./,258);
//创建或获取消息对象
int msgid msgget(key,IPC_CREAT| 0666);
//准备要发送的消息
Msg msg01 {10,张三,你好 李四};
Msg msg02;
msg02.msgType20;
strcpy(msg02.name,张三);
strcpy(msg02.text,你好 王五);
//发送消息给李四
msgsnd(msgid,msg01,sizeof(msg01) - sizeof(long),0);
//发现消息给王五
msgsnd(msgid,msg02,sizeof(msg01) - sizeof(long),0);
return 0;
} 代码 02_ls.c #include stdio.h
#include sys/types.h
#include sys/ipc.h
#include sys/msg.h
#include string.h
typedef struct struct_msg{
long msgType;
char name[20];
char text[128];
}Msg;
int main(int argc, char const *argv[])
{
key_t key ftok(./,258);
int msqid msgget(key,IPC_CREAT|0666);
Msg msg;
msgrcv(msqid,msg,sizeof(msg)-sizeof(long),10,0);
printf(李四接收到的消息为\n);
printf(姓名:%s说%s\n,msg.name,msg.text);
return 0;
} 代码03——ww.c #include stdio.h
#include sys/types.h
#include sys/ipc.h
#include sys/msg.h
#include string.h
typedef struct struct_msg{
long msgType;
char name[20];
char text[128];
}Msg;
int main(int argc, char const *argv[])
{
key_t key ftok(./,258);
int msqid msgget(key,IPC_CREAT|0666);
Msg msg;
msgrcv(msqid,msg,sizeof(msg)-sizeof(long),20,0);
printf(王五接收到的消息为\n);
printf(姓名:%s说%s\n,msg.name,msg.text);
return 0;
} 消息队列控制了解 作用 : 对消息队列删除 , 获取 , 修改等操作 语法 : 所需头文件 : #include sys/msg.h 函数 : int msgctl(int msqid, int cmd, struct msqid_ds *buf); 参数 msqid:消息队列的标识符。 cmd:函数功能的控制。 IPC_RMID删除由 msqid 指示的消息队列将它从系统中删除并破坏相关数据结构。 IPC_STAT将 msqid 相关的数据结构中各个元素的当前值存入到由 buf 指向的结构中。 IPC_SET将 msqid 相关的数据结构中的元素设置为由 buf 指向的结构中的对应值。 buf:msqid_ds 数据类型的地址用来存放或更改消息队列的属性。 返回值 成功: 返回 0 失败: 返回 -1 struct msqid_ds类型 struct msqid_ds { struct ipc_perm msg_perm; /* 所有者与权限 */ time_t msg_stime; /* 最后一条消息发送的时间 */ time_t msg_rtime; /* 最后一条消息接收的时间 */ time_t msg_ctime; /* 最后一次更改的时间 */ unsigned long __msg_cbytes; /* 队列中的当前字节数非标准 */ msgqnum_t msg_qnum; /* 队列中的当前消息数 */ msglen_t msg_qbytes; /* 队列中允许的最大字节数 */ pid_t msg_lspid; /* 最后一次发送的进程 id */ pid_t msg_lrpid; /* 最后一次接收的进程 id */ }; struct ipc_perm类型: struct ipc_perm { key_t __key; /* 提供给 msgget 的密钥 (2) */ uid_t uid; /* 所有者的有效 UID */ gid_t gid; /* 所有者的有效 GID */ uid_t cuid; /* 创建者的有效 UID */ gid_t cgid; /* 创建者的有效 GID */ unsigned short mode; /* 权限 */ unsigned short __seq; /* 序列号 */ }; 案例2多人聊天程序
#include stdio.h
#include sys/types.h
#include sys/ipc.h
#include sys/msg.h
#include unistd.h
#include sys/wait.h
#include string.h
typedef struct INFO
{long type;char name[20];char text[128];
}info;
int main(int argc, char const *argv[])
{printf(请输入用户姓名:\n);char name[50] {0};scanf(%s,name);int stype 0;printf(请输入要发送的类型:\n);scanf(%d,stype);int rtype 0;printf(请输入要接受的数据类型:\n);scanf(%d,rtype);//创建消息队列key_t key ftok(./,11) ;int mesid msgget(key,IPC_CREAT | 0666);printf(mesid%d\n,mesid);int i 0;for(i 0;i 2;i){int pid fork();if(pid 0){break;}}if(i 0){while(1){info inf;msgrcv(mesid,inf,sizeof(info)-sizeof(long),rtype,0);printf(%s:%s\n,inf.name,inf.text);if(strcmp(886,inf.text) 0){break;}printf(111\n);}_exit(0);}else if(i 1){while(1){printf(222\n); info inf;scanf(%s,inf.text);inf.type stype;strcpy(inf.name,name);msgsnd(mesid,inf,sizeof(info)-sizeof(long),0);if(strcmp(886,inf.text) 0){break;}}_exit(0);}else if(i 2){while(1){int pid waitpid(-1,NULL,WNOHANG);if(pid -1){break;}}}return 0;
}