- A+
所属分类:linux技术
匿名管道pipe
具有亲缘关系的两个进程间通信,半双工通信,要实现全双工通信需要创建两个pipe。
相关系统调用
函数名 | 作用 |
---|---|
fork() | 复制一个子进程。 |
pipe() | 创建一个管道。 |
close() | 用于关闭管道读/写端。 |
write() | 向管道写入。 |
read() | 从管道读出。 |
实例
#include <sys/types.h> #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <string.h> int main() { int result = -1; char str[] = "hello,process!"; //要写入的数据 char buf[256]; //读出缓冲区 int fd[2]; //读/写文件描述符 int *pipe_read = &fd[0]; //管道读写指针,便于区分读写文件描述符 int *pipe_write = &fd[1]; pid_t pid = -1; //进程号,用于标识子进程与父进程 result = pipe(fd); //创建管道 if(result != 0) { printf("open pipe ERRORn"); exit(0); } pid = fork(); //创建子进程 if(pid == -1) { printf("create process ERRORn"); exit(0); } if(pid == 0) { //子进程 close(*pipe_read); //关闭通道读功能 write(*pipe_write, str, strlen(str)); //管道写 close(*pipe_write); //写完关闭文件描述符 }else { close(*pipe_write); read(*pipe_read, buf, sizeof(buf)); close(*pipe_read); printf("收到子进程数据:%s", buf); } return 0; }
运行结果:
[Running] cd "/home/tayoou/pipe/" && gcc pipe.c -o pipe && "/home/tayoou/pipe/"pipe 收到子进程数据:hello,process!
命名管道fifo
无亲缘关系的进程间进行通信,是一种特殊的文件,在文件系统中以文件名的形式存在,数据存储在内存中,命名管道可以在终端创建或程序中创建。
相关函数
函数名 | 功能 |
---|---|
mkfifo() | 创建一个命名管道。 |
open() | 打开一个命名管道(文件)。 |
read() | 读命名管道(文件)。 |
write() | 写命名管道(文件)。 |
实例
fifo_write.c
#include <sys/types.h> #include <sys/stat.h> #include <stdlib.h> #include <fcntl.h> #include <unistd.h> #include <string.h> #include <stdio.h> int main() { int result = -1; int fifo_fd = -1; //命名管道文件描述符 char str[] = "hello fifo!"; result = mkfifo("myfifo", 0666); //创建命名管道,读写权限拉满,由于命名管道不可执行,因此不是0777 if(result != 0) { printf("create mkfifo FAILn"); exit(0); } fifo_fd = open("myfifo", O_WRONLY); //只写打开命名管道 //fifo_fd = open("myfifo", O_WRONLY | O_NONBLOCK); //非阻塞方式写 if(fifo_fd == -1) { printf("open fifo FAILn"); exit(0); } result = write(fifo_fd, str, strlen(str)); //向命名管道写 if(result == -1) { printf("write fifo FAILn"); exit(0); } printf("write %s to fifon", str); close(fifo_fd); return 0; }
fifo_read.c
#include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <stdio.h> #include <unistd.h> #include <string.h> #include <stdlib.h> int main() { int read_fd = -1; int result = -1; char buf[256]; read_fd = open("myfifo", O_RDONLY); //打开命名管道,只读 if(read_fd == -1) { printf("open fifo FAILn"); exit(0); } memset(buf, 0, sizeof(buf)); //数组初始化 result = read(read_fd, buf, sizeof(buf)); //从命名管道读 //fifo_fd = open("myfifo", O_WRONLY | O_NONBLOCK); //非阻塞方式读 if(result == -1) { printf("read fifo FAILn"); exit(0); } printf("recive %s from fifon", buf); close(read_fd); return 0; }
运行结果:
tayoou@:~/fifo$ ./fifo_write write hello fifo! to fifo tayoou@:~/fifo$ ./fifo_read recive hello fifo! from fifo
消息队列MQ
相关函数
函数名 | 功能 |
---|---|
msgget() | 创建/获取消息队列 |
msgsnd() | 发送消息到消息队列 |
msgrcv() | 从消息队列获取消息 |
msgctl() | 控制消息队列(包括删除) |
实例
mq_send.c
#include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> struct mq_send { long type; //消息类型,用来表示某一类消息 char data[256]; //消息内容 }; int main() { int qid = -1; //消息队列ID struct mq_send msg; int result = -1; qid = msgget((key_t)1234, IPC_CREAT | 0666); //创建消息队列,用key值来唯一标识一个消息队列,权限为0666 if(qid == -1) { printf("creat msgget FAILn"); exit(0); } while(1) { memset(msg.data, 0, sizeof(msg.data)); //初始化数组 if(fgets(msg.data, sizeof(msg.data), stdin) == NULL) { //获取键盘输入 printf("stdin FAILn"); exit(0); } msg.type = getpid(); //获得进程号,此步并非必须,可以设置type为大于0的任意值 result = msgsnd(qid, &msg, sizeof(msg.data), 0); //发送data到mq if(result == -1) { printf("send msg FAILn"); exit(0); } printf("send msg to mq: %s", msg.data); if(strcmp(msg.data, "quitn") == 0) { //退出判断逻辑 printf("quit SUCCESSn"); exit(0); } } }
mq_rcv.c
#include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> #include <stdio.h> #include <unistd.h> #include <string.h> #include <stdlib.h> struct mq_rcv { long type; char data[256]; }; int main() { int qid = -1; struct mq_rcv msg; int result = -1; qid = msgget((key_t)1234, IPC_CREAT | 0666); //使用相同的消息队列key值获取消息队列ID if(qid == -1) { printf("creat mq FAILn"); exit(0); } while(1) { result = msgrcv(qid, &msg, sizeof(msg.data), 0, 0); //从消息队列获取消息,第四个0(type)表示不按类型取,直接取mq的第一个消息。第五个0(msgflg)表示使用默认方式(阻塞)获取消息。 if(result == -1) { printf("read mq FAILn"); exit(0); } printf("recive data from mq: %s", msg.data); if(strcmp(msg.data, "quitn") == 0) { msgctl(qid, IPC_RMID, NULL); //删除消息队列。 printf("close mq SUCCESSn"); break; } } return 0; }
运行结果:
tayoou@:~/mq$ ./mq_send test send msg to mq: test nihao send msg to mq: nihao :) send msg to mq: :) quit send msg to mq: quit quit SUCCESS
tayoou@:~/mq$ ./mq_rcv recive data from mq: test recive data from mq: nihao recive data from mq: :) recive data from mq: quit close mq SUCCESS
进程信号量 system-V
本质是计数器,用于保护临界资源。不同于全局变量,信号量的P/V是原子操作。区别于线程POSIX信号量。
相关函数
函数名 | 功能 |
---|---|
semget() | 创建、获取信号量集 |
semop() | 进行PV操作 |
semctl() | 管理信号量 |