赞
踩
两个进程间,可以进行“数据”的直接传递吗?不能!进程具有独立性!
进程间通信的本质:先让不同的进程,看到同一份资源(一般都是要由 OS 提供)。
#include <unistd.h>
功能:创建一个无名管道
原型:
int pipe(int fd[2]);
参数:
fd:文件描述符数组,其中fd[0]表示读端,fd[1]表示写端
返回值:成功返回0,失败返回错误代码
实例代码
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> // 例子:从键盘读取数据,写入管道,读取管道,写到屏幕 int main() { int fds[2]; char buf[100]; int len; if (pipe(fds) == -1) perror("make pipe"), exit(1); // read from stdin while (fgets(buf, 100, stdin)) { len = strlen(buf); // write into pipe if (write(fds[1], buf, len) != len) { perror("write to pipe"); break; } memset(buf, 0x00, sizeof(buf)); // read from pipe if ((len = read(fds[0], buf, 100)) == -1) { perror("read from pipe"); break; } // write to stdout if (write(1, buf, len) != len) { perror("write to stdout"); break; } } return 0; }
所以,看待管道,就如同看待文件一样!管道的使用和文件一致,迎合了 “Linux 一切皆文件” 思想。
fork 共享管道测试代码
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/wait.h> // child void writer(int wfd) { const char *str = "hello father, I am child"; char buffer[128]; int cnt = 0; pid_t pid = getpid(); while (1) { sleep(1); char c = 'A'; write(wfd, &c, 1); cnt++; printf("cnt: %d\n", cnt); } close(wfd); } // father void reader(int rfd) { char buffer[1024]; int cnt = 10; while (1) { ssize_t n = read(rfd, buffer, sizeof(buffer) - 1); if (n > 0) printf("father get a message: %s, n: %ld\n", buffer, n); else if (n == 0) { printf("read pipe done, read file done!\n"); break; } else break; cnt--; if (cnt == 0) break; } close(rfd); printf("read endpoint close!\n"); } int main() { printf("PIPE_BUF: %d\n", _PC_PIPE_BUF); // 1. int pipefd[2]; int n = pipe(pipefd); if (n < 0) return 1; // read write printf("pipefd[0]: %d, pipefd[1]: %d\n", pipefd[0], pipefd[1]); // 3, 4 // 2. pid_t id = fork(); if (id == 0) { // child: w close(pipefd[0]); writer(pipefd[1]); exit(0); } // father: r close(pipefd[1]); reader(pipefd[0]); int status = 0; pid_t rid = waitpid(id, &status, 0); if (rid == id) { printf("exit code: %d, exit signal: %d\n", WEXITSTATUS(status), status & 0x7F); } return 0; }
命名管道可以从命令行上创建,命令行方法是使用下面这个命令:
$ mkfifo filename
命名管道也可以从程序里创建,相关函数有:
int mkfifo(const char* filename, mode_t mode);
创建命名管道:
int main(int argc, char* argv[])
{
mkfifo("p2", 0644);
return 0;
}
pipe
函数创建并打开。mkfifo
函数创建,打开用 open。$ ls -l
total 16
-rw-rw-r-- 1 ubuntu ubuntu 1009 May 4 17:16 Comm.hpp
-rw-rw-r-- 1 ubuntu ubuntu 193 May 4 15:14 Makefile
-rw-rw-r-- 1 ubuntu ubuntu 656 May 4 17:44 PipeClient.cc
-rw-rw-r-- 1 ubuntu ubuntu 929 May 4 17:44 PipeServer.cc
Makefile:
$ cat Makefile
.PHONY:all
all:pipe_client pipe_server
pipe_server:PipeServer.cc
g++ -o $@ $^ -std=c++11
pipe_client:PipeClient.cc
g++ -o $@ $^ -std=c++11
.PHONY:clean
clean:
rm -f pipe_client pipe_server
Comm.hpp:
#ifndef __COMM_HPP__ #define __COMM_HPP__ #include <iostream> #include <string> #include <cerrno> #include <cstring> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <fcntl.h> using namespace std; #define Mode 0666 #define Path "./fifo" class Fifo { public: Fifo(const string &path) : _path(path) { umask(0); int n = mkfifo(_path.c_str(), Mode); if (n == 0) { cout << "mkfifo success" << endl; } else { cerr << "mkfifo failed, errno: " << errno << ", errstring: " << strerror(errno) << endl; } } ~Fifo() { int n = unlink(_path.c_str()); if (n == 0) { cout << "remove fifo file " << _path << " success" << endl; } else { cerr << "remove failed, errno: " << errno << ", errstring: " << strerror(errno) << endl; } } private: string _path; // 文件路径 + 文件名 }; #endif
PipeServer.cc:
#include "Comm.hpp" int main() { Fifo fifo(Path); int rfd = open(Path, O_RDONLY); if (rfd < 0) { cerr << "open failed, errno: " << errno << ", errstring: " << strerror(errno) << endl; return 1; } // 如果我们的写端没打开,先读打开,open的时候就会阻塞,直到把写端打开,读open才会返回 cout << "open success" << endl; char buffer[1024]; while (true) { ssize_t n = read(rfd, buffer, sizeof(buffer) - 1); if (n > 0) { buffer[n] = 0; cout << "client sat : " << buffer << endl; } else if (n == 0) { cout << "client quit, me too!" << endl; break; } else { cerr << "read failed, errno: " << errno << ", errstring: " << strerror(errno) << endl; break; } } close(rfd); return 0; }
PipeClient.cc:
#include "Comm.hpp" int main() { int wfd = open(Path, O_WRONLY); if (wfd < 0) { cerr << "open failed, errno: " << errno << ", errstring: " << strerror(errno) << endl; return 1; } string inbuffer; while (true) { cout << "Please Enter Your Message# "; std::getline(cin, inbuffer); if (inbuffer == "quit") break; ssize_t n = write(wfd, inbuffer.c_str(), inbuffer.size()); if (n < 0) { cerr << "write failed, errno: " << errno << ", errstring: " << strerror(errno) << endl; break; } } close(wfd); return 0; }
结果:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。