一、命名管道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 <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
int main(void) {
key_t key = ftok("./9_1readfifo.c", 9);
if (key < 0) {
perror("ftok");
exit(1);
}
printf("key=0x%x\n", key);
int shmid = shmget(key, 20, IPC_CREAT | 0666);
if (shmid < 0) {
perror("shmget");
exit(1);
}
printf("shmid=%d\n", 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 <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/wait.h>
int main(void) {
key_t key = ftok("./9_1readfifo.c", 9);
if (key < 0) {
perror("ftok");
exit(1);
}
printf("key=0x%x\n", key);
int shmid = shmget(key, 20, IPC_CREAT | 0666);
if (shmid < 0) {
perror("shmget");
exit(1);
}
printf("shmid=%d\n", key);
void *shmp = shmat(shmid, NULL, 0);
if (shmp < 0) {
perror("shmat");
exit(1);
}
printf("shmp=%p\n", 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 %s\n", shmp);
bzero(shmp, 20);
}
sleep(1);
}
}
shmdt(shmp);
return 0;
}
?
4.调用当对共享存储段的操作已经结束时,则调用shmdt脱接该段。
(并不从系统中删除其标识符以及其数据结构。该标识符依然存在直到某个进程调用shmctl带命令IPC_RMID特地删除它)
shmaddr参数:以前调用shmat时返回值:返回成功为0,错误为-1.
5.调用shmctl对共享存储段执行多种操作
三、消息队列
1.系统内核维护一个存放消息的队列,不同用户可以向队列中发送信息或者队列中接收消息。
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/wait.h>
#include <sys/msg.h>
int main() {
key_t key = ftok("./tube", 9);
printf("mqid=%#x\n", key);
int mqid = msgget(key, IPC_CREAT | 0666);
printf("mqid=%d\n", mqid);
return 0;
}
2.往队列里发送一条消息。此操作被中断后不会被重启(信号处理中SA_RESTART)
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/wait.h>
#include <sys/msg.h>
#define MSGLEN 20
typedef struct msgbuf
{
long mtype;
char mtext[MSGLEN];
}MSG;
int main() {
key_t key = ftok("./tube", 9);
printf("mqid=%#x\n", key);
int mqid = msgget(key, IPC_CREAT | 0666);
printf("mqid=%d\n", 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, "haha\n", MSGLEN);
msgsnd(mqid, &msg, MSGLEN, 0);
return 0;
}
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/wait.h>
#include <sys/msg.h>
#define MSGLEN 20
typedef struct msgbuf
{
long mtype;
char mtext[MSGLEN];
}MSG;
int main() {
key_t key = ftok("./tube", 9);
printf("mqid=%#x\n", key);
int mqid = msgget(key, IPC_CREAT | 0666);
printf("mqid=%d\n", mqid);
MSG msg;
msgrcv(mqid, &msg, MSGLEN, 2, 0);
printf("msg.type=%ld\nmsg,text=%s\n", msg.mtype, msg.mtext);
msgrcv(mqid, &msg, MSGLEN, 1, 0);
printf("msg.type=%ld\nmsg,text=%s\n", msg.mtype, msg.mtext);
return 0;
}
?
?
|