#include<sys/ipc.h> key_t ftok(const char *path,int id);
key的确定规则: 用平path的stat结构中的st_dev和st_ino子u字段与id组合起来。理论上,文件不同,key也应该不同。但是因为i节点和key是 在long类型的数据结构中,如果发生越界,那么就有可能出现不同的文件产生相同的key的情况。
ipcs命令的使用:命令ipcs用于读取System V IPC目标的状态。
ipcs -q: 只显示消息队列。
ipcs -s: 只显示信号量。
ipcs -m: 只显示共享内存。
ipcs –help: 其他的参数。下面是ipcs命令输出的例子:
[root@wanglong wanglong]# ipcs
—— Shared Memory Segments ——–
key shmid owner perms bytes nattch status
0×00000000 0 root 644 40 2
0×00000000 32769 root 644 16384 2
0×00000000 65538 root 644 268 2
—— Semaphore Arrays ——–
key semid owner perms nsems
0×00000000 98305 apache 600 10×000000a7 0 root 600 1
0×00000000 65538 apache 600 1
0×00000000 131075 apache 600 1
0×00000000 163844 apache 600 1
0×00000000 196613 apache 600 1
0×00000000 229382 apache 600 1
0×00000000 262151 apache 600 1
0×00000000 294920 apache 600 1
—— Message Queues ——–
key msqid owner perms used-bytes messages
与消息队列相关的常用SYSTEM CALL。1、消息队列的创建和打开
#include<sys/msg.h> int msgget(key_t key, int flag);
成功返回消息队列的ID,出错返回-1
flag:
IPC_CREAT 如果当前的key没有与任何IPC结合,则创建IPC并返回该IPC的 标识符。如果IPC已经存在,打开IPC并返回IPC的标识符
IPC_EXCL 与IPC_CREAT连用,当IPC存在时,就出错.否则就创建
同时我们需要指定IPC的权限.例如
msgget(key,IPC_CREAT|IPC_EXCL|0666);
2、发送消息
#include<sys/msg.h> int msgsnd(int msgid, const void*ptr,size_t nbytes, int flag);
成功返回0,出错返回-1
ptr是指向消息的指针,消息的结构通常为
struct mymsg{
long mtype; //指定消息的类型,因为可以按消息类型接收
char mtext[512]; //消息的内容
};
flag:
IPC_NOWAIT 非阻塞标志,如果消息队列已满,msgsnd立即出错返回。
如果没有指定IPC_NOWAIT,msgsnd一直阻塞直到:
1、有空间可以容纳要发送的消息
2、从系统中删除了此队列(返回EIDRM)或捕捉到信号,并从信号处理程序返回 (返回EINTR)...
发送的消息会一直存在消息队列中直到有进程去取走
删除消息队列的机制不是很完善,这里并没有用引用计数.不像删除文件那样要等没有 进程访问该文件时才能删除
3、接收消息
#include<sys/msg.h> ssize_t msgrcv(int msqid, void *ptr, size_t nbytes, long type , int flag);
成功返回消息的数据部分的长度,出错返回-1
ptr是指向消息的结构体
nbytes是消息结构体中数据缓存区的长度
type对应消息结构体中type:
type == 0 返回队列的第一个消息
type > 0 返回类型为type的第一个消息
type < 0 返回队列中消息类型小于或等于type绝对值的消息
flag:
IPC_NOWAIT 如果没有找到相应的消息立即返回-1,errno为ENOMSG
MSG_NOERROR nbytes小于消息的长度时,消息被截短
当消息接收了后,该消息就从消息队列中被删除
4、msgctl函数
msgctl对队列执行多种操作
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
成功返回0,失败返回-1
cmd:
IPC_STAT 取消息队列的msqid_ds结构放在buf中
IPC_SET 按buf中的值设置msqid_ds
IPC_RMID 删除消息队列及队列中的数据
//-----------server.c-------------------------- #include<sys/ipc.h> #include<stdio.h> #include<stdlib.h> #include<sys/msg.h> #include<sys/types.h> #include<string.h> #define PATH "/home/jyl/db1" #define BUFSIZE 512 struct mymsg{ long mtype; char mtext[BUFSIZE]; }; int main(){ key_t key = ftok(PATH,1024); if(key < 0){ perror("ftok error\n"); exit(0); } int msgid = msgget(key,IPC_CREAT|IPC_EXCL|0666); if(msgid < 0){ // perror("msgget error\n"); // exit(0); printf("ipc已经存在\n"); msgid = msgget(key,IPC_CREAT); } struct mymsg msg; msg.mtype = 1; strcpy(msg.mtext,"hellochild"); if(!msgsnd(msgid, &msg, BUFSIZE,IPC_NOWAIT)){ printf("msgsend success !\n"); }else{ perror("msgsend fail\n"); exit(0); } struct msqid_ds m_ds; /* if(msgctl(msgid,IPC_RMID,&m_ds) == 0){ printf("remove success\n"); }else{ perror("remove fail\n"); exit(0); } */ return 0; } //--------client.c---------------------- #include<sys/ipc.h> #include<stdio.h> #include<stdlib.h> #include<sys/msg.h> #include<sys/types.h> #include<string.h> #define PATH "/home/jyl/db1" #define BUFSIZE 512 struct mymsg{ long mtype; char mtext[BUFSIZE]; }; int main(){ key_t key = ftok(PATH,1024); if(key < 0){ perror("ftok error\n"); exit(0); } int msgid = msgget(key,0); if(msgid < 0){ perror("msgget error\n"); exit(0); } struct mymsg msg; if(msgrcv(msgid, &msg, BUFSIZE,0,IPC_NOWAIT) > 0){ printf("%s\n",msg.mtext); }else{ perror("msgrcv fail\n"); exit(0); } struct msqid_ds buf; if(msgctl(msgid,IPC_RMID,&buf) < 0){ perror("remove ipc fail\n"); exit(0); }else{ printf("remove ipc success\n"); } return 0; }