一、命名管道FIFO
FIFO IPC机制:利用文件系统中系统文件来标识的。可以用mkfifo命令创建一个FIFO文件:
mkfifo tube
ls -l tube
FIFO文件在磁盘上没有数据块,仅用来标识内核中的一条通道,各进程可以打开这个文件进行read/write,实际上是在读写内核通道(根本原来在于file结构体所指向的read,write函数和常规文件不一样),就实现了进程间通信。
二、共享内存 1.共享存储
允许两个或多个进程共享一给定的存储区。因为数据不需要再客户机和服务器之间复制。
2.调用第一个函数是shmget,获得一个指定大小的共享存储标识符。
①key:用来标识共享内存size参数该共享存储段最小值,如果正在创建一个新段,必须指定size。如果正在存放一个现存的段,将size指定为0。
②shmflg:IPC_CREATE和IPC_EXCL,最为重要的是shmflg中指明访问权限,跟open的mode参数一样。否则出现permission denied错误。
③返回:若成功则为共享内存ID,出错则为-1。
④key由ftok()生成。pathname必须为调用进程可以访问的。pathname和proj_id共同组成一个key。
#include #include #include #include #include #include #include #include int main(void) { key_t key = ftok("./9_1readfifo.c", 9); if (key < 0) { perror("ftok"); exit(1); } printf("key=0x%xn", key); int shmid = shmget(key, 20, IPC_CREAT | 0666); if (shmid < 0) { perror("shmget"); exit(1); } printf("shmid=%dn", key); return 0;}
3.调用一旦创建一个共享存储段,进程就可调用shmat将其连接到它的地址空间中。
①返回:若成功则为指向共享存储段的指针,出错则为-1.
②共享存储段连接到调用进程的哪个地址上与addr参数以及flag中是否指定SHM_RND位有关:
如果addr=NULL:此段连接到由内核选择的第一个可用地址上。
如果addr非NULL,并没有指定SHM_RND:此段连接到addr指定的地址上。
如果addr非0,并且指定SHM_RND:此段连接到addr-(addr mod SHMLBA)表示的地址上。
SHM_RND:取整。
SHM_LBA:低边界地址倍数,总是2的乘方。
该算式将地址向下取最近1个SHMLBA的倍数。
③一般指定addr=0,以便由内核选择地址。
#include #include #include #include #include #include #include #include #include #include int main(void) { key_t key = ftok("./9_1readfifo.c", 9); if (key < 0) { perror("ftok"); exit(1); } printf("key=0x%xn", key); int shmid = shmget(key, 20, IPC_CREAT | 0666); if (shmid < 0) { perror("shmget"); exit(1); } printf("shmid=%dn", key); void *shmp = shmat(shmid, NULL, 0); if (shmp < 0) { perror("shmat"); exit(1); } printf("shmp=%pn", shmp); pid_t pid = fork(); if (pid < 0) { perror("fork"); exit(1); } if (pid) { //parent process while (1) { scanf("%s", shmp); if (!strcmp(shmp, "quit")) break; } wait(NULL); } else { //child process while (1) { if (!strcmp(shmp, "quit")) break; if (shmp) { printf("child read %sn", shmp); bzero(shmp, 20); } sleep(1); } } shmdt(shmp); return 0;}
4.调用当对共享存储段的操作已经结束时,则调用shmdt脱接该段。
(并不从系统中删除其标识符以及其数据结构。该标识符依然存在直到某个进程调用shmctl带命令IPC_RMID特地删除它)
shmaddr参数:以前调用shmat时返回值:返回成功为0,错误为-1.
5.调用shmctl对共享存储段执行多种操作 三、消息队列
1.系统内核维护一个存放消息的队列,不同用户可以向队列中发送信息或者队列中接收消息。
#include #include #include #include #include #include #include #include #include #include #include int main() { key_t key = ftok("./tube", 9); printf("mqid=%#xn", key); int mqid = msgget(key, IPC_CREAT | 0666); printf("mqid=%dn", mqid); return 0;}
2.往队列里发送一条消息。此操作被中断后不会被重启(信号处理中SA_RESTART)
#include #include #include #include #include #include #include #include #include #include #include #define MSGLEN 20typedef struct msgbuf{ long mtype; char mtext[MSGLEN];}MSG;int main() { key_t key = ftok("./tube", 9); printf("mqid=%#xn", key); int mqid = msgget(key, IPC_CREAT | 0666); printf("mqid=%dn", mqid); MSG msg; msg.mtype = 1; strncpy(msg.mtext, "how are you?n", MSGLEN); msgsnd(mqid, &msg, MSGLEN, 0); msg.mtype = 2; strncpy(msg.mtext, "hahan", MSGLEN); msgsnd(mqid, &msg, MSGLEN, 0); return 0;}
#include #include #include #include #include #include #include #include #include #include #include #define MSGLEN 20typedef struct msgbuf{ long mtype; char mtext[MSGLEN];}MSG;int main() { key_t key = ftok("./tube", 9); printf("mqid=%#xn", key); int mqid = msgget(key, IPC_CREAT | 0666); printf("mqid=%dn", mqid); MSG msg; msgrcv(mqid, &msg, MSGLEN, 2, 0); printf("msg.type=%ldnmsg,text=%sn", msg.mtype, msg.mtext); msgrcv(mqid, &msg, MSGLEN, 1, 0); printf("msg.type=%ldnmsg,text=%sn", msg.mtype, msg.mtext); return 0;}