文章目录
-
- [1. 进程间通信介绍](#1. 进程间通信介绍)
- [2. 管道](#2. 管道)
- [3. 匿名管道](#3. 匿名管道)
- [4. 命名管道](#4. 命名管道)
1. 进程间通信介绍

2. 管道
什么是管道
- 管道是Unix中最古老的进程间通信的形式。
- 我们把从一个进程连接到另一个进程的一个数据流称为一个"管道"

c
[gsm@VM-4-3-centos ~]$ who
gsm pts/0 2025-12-13 14:32 (101.94.68.192)
gsm pts/1 2025-12-13 14:32 (101.94.68.192)
[gsm@VM-4-3-centos ~]$ who | wc -l
2
[gsm@VM-4-3-centos ~]$ sleep 20000 | sleep 30000 &
[1] 10569
[gsm@VM-4-3-centos ~]$ ps ajx | head -1 && ps ajx | grep sleep
PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
1 1842 1842 1842 ? -1 Ssl 0 20:18 /bin/sh -c sleep 100
8370 10568 10568 8370 pts/1 10837 S 1001 0:00 sleep 20000
8370 10569 10568 8370 pts/1 10837 S 1001 0:00 sleep 30000
8370 10838 10837 8370 pts/1 10837 S+ 1001 0:00 grep --color=auto sleep
[gsm@VM-4-3-centos ~]$ fg 1
sleep 20000 | sleep 30000
^C
[gsm@VM-4-3-centos ~]$ ps ajx | head -1 && ps ajx | grep sleep
PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
1 1842 1842 1842 ? -1 Ssl 0 20:18 /bin/sh -c sleep 100
8370 10969 10968 8370 pts/1 10968 S+ 1001 0:00 grep --color=auto sleep
3. 匿名管道


cpp
//Makefile
mypipe:mypipe.cc
g++ -o $@ $^ -std=c++11
.PHONY:clean
clean:
rm -f mypipe
//mypipe.cc
#include <iostream>
#include <unistd.h>
int main()
{
int fds[2] = {0};
int n = pipe(fds); //fds:输出型参数
if (n == 0)
{
std::cout << "fds[0]: " << fds[0] << std::endl; // 3
std::cout << "fds[1]: " << fds[1] << std::endl; // 4
}
return 0;
}
gsm@VM-4-3-ubuntu:~/linux/112/lesson21$ ll
total 16
drwxrwxr-x 2 gsm gsm 4096 Dec 14 15:08 ./
drwxrwxr-x 20 gsm gsm 4096 Dec 13 22:38 ../
-rw-rw-r-- 1 gsm gsm 75 Dec 14 15:07 Makefile
-rw-rw-r-- 1 gsm gsm 288 Dec 14 15:19 mypipe.cc
gsm@VM-4-3-ubuntu:~/linux/112/lesson21$ make
g++ -o mypipe mypipe.cc -std=c++11
gsm@VM-4-3-ubuntu:~/linux/112/lesson21$ ls
Makefile mypipe mypipe.cc
gsm@VM-4-3-ubuntu:~/linux/112/lesson21$ ./mypipe
fds[0]: 3
fds[1]: 4
cpp
//mypipe.cc
#include <iostream>
#include <unistd.h>
int main()
{
int fds[2] = {0};
int n = pipe(fds); //fds:输出型参数
if (n != 0)
{
std::cerr << "pipe error" << std::endl;
return 1;
}
std::cout << "ok" << std::endl;
std::cout << "ok" << std::endl;
std::cout << "ok" << std::endl;
std::cout << "ok" << std::endl;
std::cout << "ok" << std::endl;
std::cerr << "pipe error" << std::endl;
std::cerr << "pipe error" << std::endl;
std::cerr << "pipe error" << std::endl;
std::cerr << "pipe error" << std::endl;
return 0;
}
gsm@VM-4-3-ubuntu:~/linux/112/lesson21$ ll
total 16
drwxrwxr-x 2 gsm gsm 4096 Dec 14 18:12 ./
drwxrwxr-x 20 gsm gsm 4096 Dec 13 22:38 ../
-rw-rw-r-- 1 gsm gsm 75 Dec 14 15:07 Makefile
-rw-rw-r-- 1 gsm gsm 590 Dec 14 18:10 mypipe.cc
gsm@VM-4-3-ubuntu:~/linux/112/lesson21$ make
g++ -o mypipe mypipe.cc -std=c++11
gsm@VM-4-3-ubuntu:~/linux/112/lesson21$ ./mypipe
ok
ok
ok
ok
ok
pipe error
pipe error
pipe error
pipe error
gsm@VM-4-3-ubuntu:~/linux/112/lesson21$ ./mypipe >log.txt
pipe error
pipe error
pipe error
pipe error
gsm@VM-4-3-ubuntu:~/linux/112/lesson21$ cat log.txt
ok
ok
ok
ok
ok
gsm@VM-4-3-ubuntu:~/linux/112/lesson21$ ./mypipe 1>log.txt
pipe error
pipe error
pipe error
pipe error
gsm@VM-4-3-ubuntu:~/linux/112/lesson21$ cat log.txt
ok
ok
ok
ok
ok
gsm@VM-4-3-ubuntu:~/linux/112/lesson21$ ./mypipe 2>log.txt
ok
ok
ok
ok
ok
gsm@VM-4-3-ubuntu:~/linux/112/lesson21$ cat log.txt
pipe error
pipe error
pipe error
pipe error
gsm@VM-4-3-ubuntu:~/linux/112/lesson21$ ./mypipe 1>log.txt 2>log.txt
gsm@VM-4-3-ubuntu:~/linux/112/lesson21$ cat log.txt
pipe error
pipe error
pipe error
pipe error
gsm@VM-4-3-ubuntu:~/linux/112/lesson21$ ./mypipe >log.txt 2>&1
gsm@VM-4-3-ubuntu:~/linux/112/lesson21$ cat log.txt
ok
ok
ok
ok
ok
pipe error
pipe error
pipe error
pipe error
gsm@VM-4-3-ubuntu:~/linux/112/lesson21$ ./mypipe 1>ok.txt 2>err.txt
gsm@VM-4-3-ubuntu:~/linux/112/lesson21$ ll
total 48
drwxrwxr-x 2 gsm gsm 4096 Dec 14 18:25 ./
drwxrwxr-x 20 gsm gsm 4096 Dec 13 22:38 ../
-rw-rw-r-- 1 gsm gsm 44 Dec 14 18:25 err.txt
-rw-rw-r-- 1 gsm gsm 59 Dec 14 18:20 log.txt
-rw-rw-r-- 1 gsm gsm 75 Dec 14 15:07 Makefile
-rwxrwxr-x 1 gsm gsm 16712 Dec 14 18:12 mypipe*
-rw-rw-r-- 1 gsm gsm 590 Dec 14 18:10 mypipe.cc
-rw-rw-r-- 1 gsm gsm 15 Dec 14 18:25 ok.txt
gsm@VM-4-3-ubuntu:~/linux/112/lesson21$ cat ok.txt
ok
ok
ok
ok
ok
gsm@VM-4-3-ubuntu:~/linux/112/lesson21$ cat err.txt
pipe error
pipe error
pipe error
pipe error
cpp
//mypipe.cc
#include <iostream>
#include <string>
#include <cstdlib>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
// Father process -> read
// Child process -> write
int main()
{
// 1. 创建管道
int fds[2] = {0};
int n = pipe(fds); // fds:输出型参数
if (n != 0)
{
std::cerr << "pipe error" << std::endl;
return 1;
}
// 2. 创建子进程
pid_t id = fork();
if (id < 0)
{
std::cerr << "fork error" << std::endl;
return 2;
}
else if (id == 0)
{
// 子进程
// 3. 关闭不需要的fd,关闭read
close(fds[0]);
int cnt = 0;
while (true)
{
std::string message = "hello bit, hello ";
message += std::to_string(getpid());
message += ", ";
message += std::to_string(cnt);
//fds[1]
::write(fds[1], message.c_str(), message.size());
cnt++;
sleep(1);
}
exit(0);
}
else
{
// 父进程
// 3. 关闭不需要的fd,关闭write
close(fds[1]);
char buffer[1024];
while (true)
{
ssize_t n = ::read(fds[0], buffer, 1024);
if (n > 0)
{
buffer[n] = 0;
std::cout << "child->father, message: " << buffer << std::endl;
}
}
pid_t rid = waitpid(id, nullptr, 0);
std::cout << "father wait child success: " << rid << std::endl;
}
return 0;
}
gsm@VM-4-3-ubuntu:~/linux/112/lesson21$ ll
total 16
drwxrwxr-x 2 gsm gsm 4096 Dec 15 14:34 ./
drwxrwxr-x 20 gsm gsm 4096 Dec 13 22:38 ../
-rw-rw-r-- 1 gsm gsm 75 Dec 14 22:04 Makefile
-rw-rw-r-- 1 gsm gsm 1580 Dec 15 14:26 mypipe.cc
gsm@VM-4-3-ubuntu:~/linux/112/lesson21$ make
g++ -o mypipe mypipe.cc -std=c++11
gsm@VM-4-3-ubuntu:~/linux/112/lesson21$ ./mypipe
child->father, message: hello bit, hello 768132, 0
child->father, message: hello bit, hello 768132, 1
child->father, message: hello bit, hello 768132, 2
child->father, message: hello bit, hello 768132, 3
child->father, message: hello bit, hello 768132, 4
child->father, message: hello bit, hello 768132, 5
^C
gsm@VM-4-3-ubuntu:~/linux/112/lesson21$ ps ajx | grep mypipe
739790 768131 768131 739790 pts/0 768131 S+ 1002 0:00 ./mypipe
768131 768132 768131 739790 pts/0 768131 S+ 1002 0:00 ./mypipe
740293 768137 768136 740293 pts/5 768136 R+ 1002 0:00 grep --color=auto mypipe
cpp
//mypipe.cc
#include <iostream>
#include <string>
#include <cstdlib>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
// Father process -> read
// Child process -> write
int main()
{
// 1. 创建管道
int fds[2] = {0};
int n = pipe(fds); // fds:输出型参数
if (n != 0)
{
std::cerr << "pipe error" << std::endl;
return 1;
}
// 2. 创建子进程
pid_t id = fork();
if (id < 0)
{
std::cerr << "fork error" << std::endl;
return 2;
}
else if (id == 0)
{
// 子进程
// 3. 关闭不需要的fd,关闭read
close(fds[0]);
int cnt = 0;
int total = 0;
while (true)
{
std::string message = "h";
// message += std::to_string(getpid());
// message += ", ";
// message += std::to_string(cnt);
//fds[1]
total += ::write(fds[1], message.c_str(), message.size());
cnt++;
std::cout << "total: " << total << std::endl;
//sleep(1);
}
exit(0);
}
else
{
// 父进程
// 3. 关闭不需要的fd,关闭write
close(fds[1]);
char buffer[1024];
while (true)
{
sleep(100);
ssize_t n = ::read(fds[0], buffer, 1024);
if (n > 0)
{
buffer[n] = 0;
std::cout << "child->father, message: " << buffer << std::endl;
}
}
pid_t rid = waitpid(id, nullptr, 0);
std::cout << "father wait child success: " << rid << std::endl;
}
return 0;
}
gsm@VM-4-3-ubuntu:~/linux/112/lesson21$ ll
total 16
drwxrwxr-x 2 gsm gsm 4096 Dec 15 18:04 ./
drwxrwxr-x 20 gsm gsm 4096 Dec 13 22:38 ../
-rw-rw-r-- 1 gsm gsm 75 Dec 14 22:04 Makefile
-rw-rw-r-- 1 gsm gsm 1689 Dec 15 18:00 mypipe.cc
gsm@VM-4-3-ubuntu:~/linux/112/lesson21$ make
g++ -o mypipe mypipe.cc -std=c++11
gsm@VM-4-3-ubuntu:~/linux/112/lesson21$ ./mypipe
// ...
total: 65531
total: 65532
total: 65533
total: 65534
total: 65535
total: 65536
^C
cpp
//mypipe.cc
#include <iostream>
#include <string>
#include <cstdlib>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
// Father process -> read
// Child process -> write
int main()
{
// 1. 创建管道
int fds[2] = {0};
int n = pipe(fds); // fds:输出型参数
if (n != 0)
{
std::cerr << "pipe error" << std::endl;
return 1;
}
// 2. 创建子进程
pid_t id = fork();
if (id < 0)
{
std::cerr << "fork error" << std::endl;
return 2;
}
else if (id == 0)
{
// 子进程
// 3. 关闭不需要的fd,关闭read
close(fds[0]);
int cnt = 0;
int total = 0;
while (true)
{
std::string message = "h";
// message += std::to_string(getpid());
// message += ", ";
// message += std::to_string(cnt);
//fds[1]
total += ::write(fds[1], message.c_str(), message.size());
cnt++;
std::cout << "total: " << total << std::endl;
//sleep(1);
}
exit(0);
}
else
{
// 父进程
// 3. 关闭不需要的fd,关闭write
close(fds[1]);
char buffer[1024];
while (true)
{
sleep(1);
ssize_t n = ::read(fds[0], buffer, 1024);
if (n > 0)
{
buffer[n] = 0;
std::cout << "child->father, message: " << buffer << std::endl;
}
}
pid_t rid = waitpid(id, nullptr, 0);
std::cout << "father wait child success: " << rid << std::endl;
}
return 0;
}
cpp
//mypipi.cc
#include <iostream>
#include <string>
#include <cstdlib>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
// Father process -> read
// Child process -> write
int main()
{
// 1. 创建管道
int fds[2] = {0};
int n = pipe(fds); // fds:输出型参数
if (n != 0)
{
std::cerr << "pipe error" << std::endl;
return 1;
}
// 2. 创建子进程
pid_t id = fork();
if (id < 0)
{
std::cerr << "fork error" << std::endl;
return 2;
}
else if (id == 0)
{
// 子进程
// 3. 关闭不需要的fd,关闭read
close(fds[0]);
int cnt = 0;
int total = 0;
while (true)
{
std::string message = "h";
// message += std::to_string(getpid());
// message += ", ";
// message += std::to_string(cnt);
//fds[1]
total += ::write(fds[1], message.c_str(), message.size());
cnt++;
std::cout << "total: " << total << std::endl;
sleep(1);
break;
}
exit(0);
}
else
{
// 父进程
// 3. 关闭不需要的fd,关闭write
close(fds[1]);
char buffer[1024];
while (true)
{
sleep(1);
ssize_t n = ::read(fds[0], buffer, 1024);
if (n > 0)
{
buffer[n] = 0;
std::cout << "child->father, message: " << buffer << std::endl;
}
else if (n == 0)
{
// 如果写端关闭
// 读端读完管道内部的数据,在读取的时候
// 就会读取到返回值0,表示对端关闭,也表示读到文件结尾
std::cout << "n:" << n << std::endl;
std::cout << "child quit ??? me too" << std::endl;
break;
}
std::cout << std::endl;
}
pid_t rid = waitpid(id, nullptr, 0);
std::cout << "father wait child success: " << rid << std::endl;
}
return 0;
}
gsm@VM-4-3-ubuntu:~/linux/112/lesson21$ ll
total 16
drwxrwxr-x 2 gsm gsm 4096 Dec 15 18:46 ./
drwxrwxr-x 20 gsm gsm 4096 Dec 13 22:38 ../
-rw-rw-r-- 1 gsm gsm 75 Dec 14 22:04 Makefile
-rw-rw-r-- 1 gsm gsm 2150 Dec 15 18:46 mypipe.cc
gsm@VM-4-3-ubuntu:~/linux/112/lesson21$ make
g++ -o mypipe mypipe.cc -std=c++11
gsm@VM-4-3-ubuntu:~/linux/112/lesson21$ ./mypipe
total: 1
child->father, message: h
n:0
child quit ??? me too
father wait child success: 840782
cpp
//mypipe.cc
#include <iostream>
#include <string>
#include <cstdlib>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
// Father process -> read
// Child process -> write
int main()
{
// 1. 创建管道
int fds[2] = {0};
int n = pipe(fds); // fds:输出型参数
if (n != 0)
{
std::cerr << "pipe error" << std::endl;
return 1;
}
// 2. 创建子进程
pid_t id = fork();
if (id < 0)
{
std::cerr << "fork error" << std::endl;
return 2;
}
else if (id == 0)
{
// 子进程
// 3. 关闭不需要的fd,关闭read
close(fds[0]);
int cnt = 0;
int total = 0;
while (true)
{
std::string message = "h";
// message += std::to_string(getpid());
// message += ", ";
// message += std::to_string(cnt);
// fds[1]
total += ::write(fds[1], message.c_str(), message.size());
cnt++;
std::cout << "total: " << total << std::endl;
sleep(2);
// break;
}
exit(0);
}
else
{
// 父进程
// 3. 关闭不需要的fd,关闭write
close(fds[1]);
char buffer[1024];
while (true)
{
sleep(1);
ssize_t n = ::read(fds[0], buffer, 1024);
if (n > 0)
{
buffer[n] = 0;
std::cout << "child->father, message: " << buffer << std::endl;
}
else if (n == 0)
{
// 如果写端关闭
// 读端读完管道内部的数据,在读取的时候
// 就会读取到返回值0,表示对端关闭,也表示读到文件结尾
std::cout << "n:" << n << std::endl;
std::cout << "child quit ??? me too" << std::endl;
break;
}
close(fds[0]);
break;
std::cout << std::endl;
}
int status = 0;
pid_t rid = waitpid(id, &status, 0);
std::cout << "father wait child success: " << rid << " exit code: " <<
((status >> 8) & 0xFF) << ", exit sig: " << (status & 0x7F) << std::endl;
}
return 0;
}
gsm@VM-4-3-ubuntu:~/linux/112/lesson21$ ll
total 16
drwxrwxr-x 2 gsm gsm 4096 Dec 15 19:10 ./
drwxrwxr-x 20 gsm gsm 4096 Dec 13 22:38 ../
-rw-rw-r-- 1 gsm gsm 75 Dec 14 22:04 Makefile
-rw-rw-r-- 1 gsm gsm 2298 Dec 15 19:10 mypipe.cc
gsm@VM-4-3-ubuntu:~/linux/112/lesson21$ make
g++ -o mypipe mypipe.cc -std=c++11
gsm@VM-4-3-ubuntu:~/linux/112/lesson21$ ./mypipe
total: 1
child->father, message: h
father wait child success: 848230 exit code: 0, exit sig: 13
gsm@VM-4-3-ubuntu:~/linux/112/lesson21$ kill -l
1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP
6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1
11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM
16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP
21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ
26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR
31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3
38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8
43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12
53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7
58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2
63) SIGRTMAX-1 64) SIGRTMAX

c
//Makefile
BIN=processpool
CC=g++
FLAGS=-Wall -std=c++11
LDFLAGS=-o
SRC=$(shell ls *.cc)
.PHONY:test
test:
@echo $(SRC)
gsm@VM-4-3-ubuntu:~/linux/112/lesson21/processpool$ ll
total 12
drwxrwxr-x 2 gsm gsm 4096 Dec 15 22:38 ./
drwxrwxr-x 4 gsm gsm 4096 Dec 15 22:37 ../
-rw-rw-r-- 1 gsm gsm 110 Dec 15 22:46 Makefile
-rw-rw-r-- 1 gsm gsm 0 Dec 15 22:43 processpool.cc
gsm@VM-4-3-ubuntu:~/linux/112/lesson21/processpool$ make test
processpool.cc
gsm@VM-4-3-ubuntu:~/linux/112/lesson21/processpool$ touch code{1..10}.cc
gsm@VM-4-3-ubuntu:~/linux/112/lesson21/processpool$ ll
total 12
drwxrwxr-x 2 gsm gsm 4096 Dec 15 22:47 ./
drwxrwxr-x 4 gsm gsm 4096 Dec 15 22:37 ../
-rw-rw-r-- 1 gsm gsm 0 Dec 15 22:47 code10.cc
-rw-rw-r-- 1 gsm gsm 0 Dec 15 22:47 code1.cc
-rw-rw-r-- 1 gsm gsm 0 Dec 15 22:47 code2.cc
-rw-rw-r-- 1 gsm gsm 0 Dec 15 22:47 code3.cc
-rw-rw-r-- 1 gsm gsm 0 Dec 15 22:47 code4.cc
-rw-rw-r-- 1 gsm gsm 0 Dec 15 22:47 code5.cc
-rw-rw-r-- 1 gsm gsm 0 Dec 15 22:47 code6.cc
-rw-rw-r-- 1 gsm gsm 0 Dec 15 22:47 code7.cc
-rw-rw-r-- 1 gsm gsm 0 Dec 15 22:47 code8.cc
-rw-rw-r-- 1 gsm gsm 0 Dec 15 22:47 code9.cc
-rw-rw-r-- 1 gsm gsm 110 Dec 15 22:46 Makefile
-rw-rw-r-- 1 gsm gsm 0 Dec 15 22:43 processpool.cc
gsm@VM-4-3-ubuntu:~/linux/112/lesson21/processpool$ make
code10.cc code1.cc code2.cc code3.cc code4.cc code5.cc code6.cc code7.cc code8.cc code9.cc processpool.cc
c
//Makefile
BIN=processpool
CC=g++
FLAGS=-Wall -std=c++11
LDFLAGS=-o
# SRC=$(shell ls *.cc)
SRC=$(wildcard *.cc)
.PHONY:test
test:
@echo $(SRC)
gsm@VM-4-3-ubuntu:~/linux/112/lesson21/processpool$ ll
total 12
drwxrwxr-x 2 gsm gsm 4096 Dec 15 22:47 ./
drwxrwxr-x 4 gsm gsm 4096 Dec 15 22:37 ../
-rw-rw-r-- 1 gsm gsm 0 Dec 15 22:47 code10.cc
-rw-rw-r-- 1 gsm gsm 0 Dec 15 22:47 code1.cc
-rw-rw-r-- 1 gsm gsm 0 Dec 15 22:47 code2.cc
-rw-rw-r-- 1 gsm gsm 0 Dec 15 22:47 code3.cc
-rw-rw-r-- 1 gsm gsm 0 Dec 15 22:47 code4.cc
-rw-rw-r-- 1 gsm gsm 0 Dec 15 22:47 code5.cc
-rw-rw-r-- 1 gsm gsm 0 Dec 15 22:47 code6.cc
-rw-rw-r-- 1 gsm gsm 0 Dec 15 22:47 code7.cc
-rw-rw-r-- 1 gsm gsm 0 Dec 15 22:47 code8.cc
-rw-rw-r-- 1 gsm gsm 0 Dec 15 22:47 code9.cc
-rw-rw-r-- 1 gsm gsm 133 Dec 15 22:50 Makefile
-rw-rw-r-- 1 gsm gsm 0 Dec 15 22:43 processpool.cc
gsm@VM-4-3-ubuntu:~/linux/112/lesson21/processpool$ make
code10.cc code1.cc code2.cc code3.cc code4.cc code5.cc code6.cc code7.cc code8.cc code9.cc processpool.cc
c
//Makefile
BIN=processpool
CC=g++
FLAGS=-Wall -std=c++11
LDFLAGS=-o
# SRC=$(shell ls *.cc)
SRC=$(wildcard *.cc)
OBJ=$(SRC:.cc=.o)
.PHONY:test
test:
@echo $(SRC)
@echo $(OBJ)
gsm@VM-4-3-ubuntu:~/linux/112/lesson21/processpool$ ll
total 12
drwxrwxr-x 2 gsm gsm 4096 Dec 15 22:47 ./
drwxrwxr-x 4 gsm gsm 4096 Dec 15 22:37 ../
-rw-rw-r-- 1 gsm gsm 0 Dec 15 22:47 code10.cc
-rw-rw-r-- 1 gsm gsm 0 Dec 15 22:47 code1.cc
-rw-rw-r-- 1 gsm gsm 0 Dec 15 22:47 code2.cc
-rw-rw-r-- 1 gsm gsm 0 Dec 15 22:47 code3.cc
-rw-rw-r-- 1 gsm gsm 0 Dec 15 22:47 code4.cc
-rw-rw-r-- 1 gsm gsm 0 Dec 15 22:47 code5.cc
-rw-rw-r-- 1 gsm gsm 0 Dec 15 22:47 code6.cc
-rw-rw-r-- 1 gsm gsm 0 Dec 15 22:47 code7.cc
-rw-rw-r-- 1 gsm gsm 0 Dec 15 22:47 code8.cc
-rw-rw-r-- 1 gsm gsm 0 Dec 15 22:47 code9.cc
-rw-rw-r-- 1 gsm gsm 165 Dec 15 22:52 Makefile
-rw-rw-r-- 1 gsm gsm 0 Dec 15 22:43 processpool.cc
gsm@VM-4-3-ubuntu:~/linux/112/lesson21/processpool$ make
code10.cc code1.cc code2.cc code3.cc code4.cc code5.cc code6.cc code7.cc code8.cc code9.cc processpool.cc
code10.o code1.o code2.o code3.o code4.o code5.o code6.o code7.o code8.o code9.o processpool.o
gsm@VM-4-3-ubuntu:~/linux/112/lesson21/processpool$ ll
total 12
drwxrwxr-x 2 gsm gsm 4096 Dec 15 22:47 ./
drwxrwxr-x 4 gsm gsm 4096 Dec 15 22:37 ../
-rw-rw-r-- 1 gsm gsm 0 Dec 15 22:47 code10.cc
-rw-rw-r-- 1 gsm gsm 0 Dec 15 22:47 code1.cc
-rw-rw-r-- 1 gsm gsm 0 Dec 15 22:47 code2.cc
-rw-rw-r-- 1 gsm gsm 0 Dec 15 22:47 code3.cc
-rw-rw-r-- 1 gsm gsm 0 Dec 15 22:47 code4.cc
-rw-rw-r-- 1 gsm gsm 0 Dec 15 22:47 code5.cc
-rw-rw-r-- 1 gsm gsm 0 Dec 15 22:47 code6.cc
-rw-rw-r-- 1 gsm gsm 0 Dec 15 22:47 code7.cc
-rw-rw-r-- 1 gsm gsm 0 Dec 15 22:47 code8.cc
-rw-rw-r-- 1 gsm gsm 0 Dec 15 22:47 code9.cc
-rw-rw-r-- 1 gsm gsm 165 Dec 15 22:52 Makefile
-rw-rw-r-- 1 gsm gsm 0 Dec 15 22:43 processpool.cc
c
//Makefile
BIN=processpool
CC=g++
FLAGS=-c -Wall -std=c++11
LDFLAGS=-o
# SRC=$(shell ls *.cc)
SRC=$(wildcard *.cc)
OBJ=$(SRC:.cc=.o)
$(BIN):$(OBJ)
$(CC) $(LDFLAGS) $@ $^
%.o:%.cc
$(CC) $(FLAGS) $<
.PHONY:clean
clean:
rm -f $(BIN) $(OBJ)
.PHONY:test
test:
@echo $(SRC)
@echo $(OBJ)
//processpool.cc
#include <iostream>
int main()
{
std::cout << "hello world!\n" << std::endl;
return 0;
}
gsm@VM-4-3-ubuntu:~/linux/112/lesson21/processpool$ ll
total 16
drwxrwxr-x 2 gsm gsm 4096 Dec 15 23:06 ./
drwxrwxr-x 4 gsm gsm 4096 Dec 15 22:37 ../
-rw-rw-r-- 1 gsm gsm 0 Dec 15 22:47 code10.cc
-rw-rw-r-- 1 gsm gsm 0 Dec 15 22:47 code1.cc
-rw-rw-r-- 1 gsm gsm 0 Dec 15 22:47 code2.cc
-rw-rw-r-- 1 gsm gsm 0 Dec 15 22:47 code3.cc
-rw-rw-r-- 1 gsm gsm 0 Dec 15 22:47 code4.cc
-rw-rw-r-- 1 gsm gsm 0 Dec 15 22:47 code5.cc
-rw-rw-r-- 1 gsm gsm 0 Dec 15 22:47 code6.cc
-rw-rw-r-- 1 gsm gsm 0 Dec 15 22:47 code7.cc
-rw-rw-r-- 1 gsm gsm 0 Dec 15 22:47 code8.cc
-rw-rw-r-- 1 gsm gsm 0 Dec 15 22:47 code9.cc
-rw-rw-r-- 1 gsm gsm 277 Dec 15 23:02 Makefile
-rw-rw-r-- 1 gsm gsm 97 Dec 15 23:07 processpool.cc
gsm@VM-4-3-ubuntu:~/linux/112/lesson21/processpool$ make
g++ -c -Wall -std=c++11 code10.cc
g++ -c -Wall -std=c++11 code1.cc
g++ -c -Wall -std=c++11 code2.cc
g++ -c -Wall -std=c++11 code3.cc
g++ -c -Wall -std=c++11 code4.cc
g++ -c -Wall -std=c++11 code5.cc
g++ -c -Wall -std=c++11 code6.cc
g++ -c -Wall -std=c++11 code7.cc
g++ -c -Wall -std=c++11 code8.cc
g++ -c -Wall -std=c++11 code9.cc
g++ -c -Wall -std=c++11 processpool.cc
g++ -o processpool code10.o code1.o code2.o code3.o code4.o code5.o code6.o code7.o code8.o code9.o processpool.o
gsm@VM-4-3-ubuntu:~/linux/112/lesson21/processpool$ ll
total 80
drwxrwxr-x 2 gsm gsm 4096 Dec 15 23:08 ./
drwxrwxr-x 4 gsm gsm 4096 Dec 15 22:37 ../
-rw-rw-r-- 1 gsm gsm 0 Dec 15 22:47 code10.cc
-rw-rw-r-- 1 gsm gsm 936 Dec 15 23:08 code10.o
-rw-rw-r-- 1 gsm gsm 0 Dec 15 22:47 code1.cc
-rw-rw-r-- 1 gsm gsm 936 Dec 15 23:08 code1.o
-rw-rw-r-- 1 gsm gsm 0 Dec 15 22:47 code2.cc
-rw-rw-r-- 1 gsm gsm 936 Dec 15 23:08 code2.o
-rw-rw-r-- 1 gsm gsm 0 Dec 15 22:47 code3.cc
-rw-rw-r-- 1 gsm gsm 936 Dec 15 23:08 code3.o
-rw-rw-r-- 1 gsm gsm 0 Dec 15 22:47 code4.cc
-rw-rw-r-- 1 gsm gsm 936 Dec 15 23:08 code4.o
-rw-rw-r-- 1 gsm gsm 0 Dec 15 22:47 code5.cc
-rw-rw-r-- 1 gsm gsm 936 Dec 15 23:08 code5.o
-rw-rw-r-- 1 gsm gsm 0 Dec 15 22:47 code6.cc
-rw-rw-r-- 1 gsm gsm 936 Dec 15 23:08 code6.o
-rw-rw-r-- 1 gsm gsm 0 Dec 15 22:47 code7.cc
-rw-rw-r-- 1 gsm gsm 936 Dec 15 23:08 code7.o
-rw-rw-r-- 1 gsm gsm 0 Dec 15 22:47 code8.cc
-rw-rw-r-- 1 gsm gsm 936 Dec 15 23:08 code8.o
-rw-rw-r-- 1 gsm gsm 0 Dec 15 22:47 code9.cc
-rw-rw-r-- 1 gsm gsm 936 Dec 15 23:08 code9.o
-rw-rw-r-- 1 gsm gsm 277 Dec 15 23:02 Makefile
-rwxrwxr-x 1 gsm gsm 16912 Dec 15 23:08 processpool*
-rw-rw-r-- 1 gsm gsm 97 Dec 15 23:07 processpool.cc
-rw-rw-r-- 1 gsm gsm 2800 Dec 15 23:08 processpool.o
gsm@VM-4-3-ubuntu:~/linux/112/lesson21/processpool$ ./processpool
hello world!
gsm@VM-4-3-ubuntu:~/linux/112/lesson21/processpool$ make clean
rm -f processpool code10.o code1.o code2.o code3.o code4.o code5.o code6.o code7.o code8.o code9.o processpool.o
gsm@VM-4-3-ubuntu:~/linux/112/lesson21/processpool$ ll
total 16
drwxrwxr-x 2 gsm gsm 4096 Dec 15 23:08 ./
drwxrwxr-x 4 gsm gsm 4096 Dec 15 22:37 ../
-rw-rw-r-- 1 gsm gsm 0 Dec 15 22:47 code10.cc
-rw-rw-r-- 1 gsm gsm 0 Dec 15 22:47 code1.cc
-rw-rw-r-- 1 gsm gsm 0 Dec 15 22:47 code2.cc
-rw-rw-r-- 1 gsm gsm 0 Dec 15 22:47 code3.cc
-rw-rw-r-- 1 gsm gsm 0 Dec 15 22:47 code4.cc
-rw-rw-r-- 1 gsm gsm 0 Dec 15 22:47 code5.cc
-rw-rw-r-- 1 gsm gsm 0 Dec 15 22:47 code6.cc
-rw-rw-r-- 1 gsm gsm 0 Dec 15 22:47 code7.cc
-rw-rw-r-- 1 gsm gsm 0 Dec 15 22:47 code8.cc
-rw-rw-r-- 1 gsm gsm 0 Dec 15 22:47 code9.cc
-rw-rw-r-- 1 gsm gsm 277 Dec 15 23:02 Makefile
-rw-rw-r-- 1 gsm gsm 97 Dec 15 23:07 processpool.cc
cpp
//processpool.cc
#include <iostream>
#include <string>
#include <vector>
#include <cstdlib>
#include <unistd.h>
#include <sys/types.h>
#include <functional>
// const int num = 5;
// typedef std::function<void()> work_t;
using work_t = std::function<void()>;
enum
{
OK = 0,
UsageError,
PipeError,
ForkError
};
// 先描述
class Channel
{
public:
Channel(int wfd, pid_t who)
: _wfd(wfd)
, _who(who)
{
// Channel-3-1234
_name = "Channel-" + std::to_string(wfd) + "-" + std::to_string(who);
}
std::string Name()
{
return _name;
}
~Channel()
{
}
private:
int _wfd;
std::string _name;
pid_t _who;
};
void Usage(std::string proc)
{
std::cout << "Usage: " << proc << " process-num" << std::endl;
}
void Worker()
{
// read->0
sleep(10);
}
// channels : 输出型参数
// work_t work: 回调
int InitProcessPool(const int& processnum, std::vector<Channel>& channels, work_t work)
{
// 2. 创建指定个数个进程
for (int i = 0; i < processnum; i++)
{
// 1. 先有管道
int pipefd[2] = {0};
int n = pipe(pipefd);
if (n < 0)
{
return PipeError;
}
// 2. 创建进程
pid_t id = fork();
if (id < 0)
{
return ForkError;
}
// 3. 建立通信信道
if (id == 0)
{
::close(pipefd[1]); // read
// child
dup2(pipefd[0], 0);
work();
::exit(0);
}
// 父进程执行
::close(pipefd[0]); // write
channels.emplace_back(pipefd[1], id);
// Channel ch(pipefd[1], id);
// channels.push_back(ch);
}
return OK;
}
void DebugPrint(std::vector<Channel>& channels)
{
for (auto& c : channels)
{
std::cout << c.Name() << std::endl;
}
}
// 我们自己就是master
int main(int argc, char *argv[])
{
if (argc != 2)
{
Usage(argv[0]);
return UsageError;
}
int num = std::stoi(argv[1]);
std::vector<Channel> channels;
// 1. 初始化进程池
InitProcessPool(num, channels, Worker);
DebugPrint(channels);
sleep(100);
return 0;
}
gsm@VM-4-3-ubuntu:~/linux/112/lesson21/processpool$ ll
total 16
drwxrwxr-x 2 gsm gsm 4096 Dec 16 11:59 ./
drwxrwxr-x 4 gsm gsm 4096 Dec 15 22:37 ../
-rw-rw-r-- 1 gsm gsm 277 Dec 15 23:02 Makefile
-rw-rw-r-- 1 gsm gsm 2231 Dec 16 11:58 processpool.cc
gsm@VM-4-3-ubuntu:~/linux/112/lesson21/processpool$ make
g++ -c -Wall -std=c++11 processpool.cc
g++ -o processpool processpool.o
gsm@VM-4-3-ubuntu:~/linux/112/lesson21/processpool$ ./processpool 10
Channel-4-1160686
Channel-5-1160687
Channel-6-1160688
Channel-7-1160689
Channel-8-1160690
Channel-9-1160691
Channel-10-1160692
Channel-11-1160693
Channel-12-1160694
Channel-13-1160695
^C
gsm@VM-4-3-ubuntu:~/linux/112/lesson21/processpool$ ./processpool 5
Channel-4-1160722
Channel-5-1160723
Channel-6-1160724
Channel-7-1160725
Channel-8-1160726
^C
gsm@VM-4-3-ubuntu:~/linux/112/lesson21/processpool$ ./processpool 3
Channel-4-1161350
Channel-5-1161351
Channel-6-1161352
^C
gsm@VM-4-3-ubuntu:~$ ps ajx | grep processpool
1127312 1160685 1160685 1127312 pts/0 1160685 S+ 1002 0:00 ./processpool 10
1160685 1160686 1160685 1127312 pts/0 1160685 S+ 1002 0:00 ./processpool 10
1160685 1160687 1160685 1127312 pts/0 1160685 S+ 1002 0:00 ./processpool 10
1160685 1160688 1160685 1127312 pts/0 1160685 S+ 1002 0:00 ./processpool 10
1160685 1160689 1160685 1127312 pts/0 1160685 S+ 1002 0:00 ./processpool 10
1160685 1160690 1160685 1127312 pts/0 1160685 S+ 1002 0:00 ./processpool 10
1160685 1160691 1160685 1127312 pts/0 1160685 S+ 1002 0:00 ./processpool 10
1160685 1160692 1160685 1127312 pts/0 1160685 S+ 1002 0:00 ./processpool 10
1160685 1160693 1160685 1127312 pts/0 1160685 S+ 1002 0:00 ./processpool 10
1160685 1160694 1160685 1127312 pts/0 1160685 S+ 1002 0:00 ./processpool 10
1160685 1160695 1160685 1127312 pts/0 1160685 S+ 1002 0:00 ./processpool 10
1159407 1160703 1160702 1159407 pts/1 1160702 S+ 1002 0:00 grep --color=auto processpool
gsm@VM-4-3-ubuntu:~$ ps ajx | grep processpool
1127312 1160721 1160721 1127312 pts/0 1160721 S+ 1002 0:00 ./processpool 5
1160721 1160722 1160721 1127312 pts/0 1160721 S+ 1002 0:00 ./processpool 5
1160721 1160723 1160721 1127312 pts/0 1160721 S+ 1002 0:00 ./processpool 5
1160721 1160724 1160721 1127312 pts/0 1160721 S+ 1002 0:00 ./processpool 5
1160721 1160725 1160721 1127312 pts/0 1160721 S+ 1002 0:00 ./processpool 5
1160721 1160726 1160721 1127312 pts/0 1160721 S+ 1002 0:00 ./processpool 5
1159407 1160751 1160750 1159407 pts/1 1160750 S+ 1002 0:00 grep --color=auto processpool
gsm@VM-4-3-ubuntu:~$ ps ajx | grep processpool
1127312 1161349 1161349 1127312 pts/0 1161349 S+ 1002 0:00 ./processpool 3
1161349 1161350 1161349 1127312 pts/0 1161349 S+ 1002 0:00 ./processpool 3
1161349 1161351 1161349 1127312 pts/0 1161349 S+ 1002 0:00 ./processpool 3
1161349 1161352 1161349 1127312 pts/0 1161349 S+ 1002 0:00 ./processpool 3
1159407 1161360 1161359 1159407 pts/1 1161359 S+ 1002 0:00 grep --color=auto processpool
cpp
//Task.hpp
#pragma once
#include <iostream>
#include <unordered_map>
#include <functional>
#include <ctime>
#include <sys/types.h>
#include <unistd.h>
using task_t = std::function<void()>;
void DownLoad()
{
std::cout << "我是下载任务..., pid: " << getpid() << std::endl;
}
void Log()
{
std::cout << "我是日志任务..., pid: " << getpid() << std::endl;
}
void Sql()
{
std::cout << "我是数据库同步任务..., pid: " << getpid() << std::endl;
}
static int number = 0;
class TaskManager
{
public:
TaskManager()
{
srand(time(nullptr));
InsertTask(DownLoad);
InsertTask(Log);
InsertTask(Sql);
}
void InsertTask(task_t t)
{
_tasks[number++] = t;
}
int SelectTask()
{
return rand() % number;
}
void Excute(int number)
{
if (_tasks.find(number) == _tasks.end())
{
return;
}
_tasks[number]();
}
~TaskManager()
{
}
private:
std::unordered_map<int, task_t> _tasks;
};
TaskManager tm;
//processpool.cc
#include <iostream>
#include <string>
#include <vector>
#include <cstdlib>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <functional>
#include "Task.hpp"
// const int num = 5;
// typedef std::function<void()> work_t;
using work_t = std::function<void()>;
enum
{
OK = 0,
UsageError,
PipeError,
ForkError
};
void Usage(std::string proc)
{
std::cout << "Usage: " << proc << " process-num" << std::endl;
}
// 先描述
class Channel
{
public:
Channel(int wfd, pid_t who)
: _wfd(wfd)
, _who(who)
{
// Channel-3-1234
_name = "Channel-" + std::to_string(wfd) + "-" + std::to_string(who);
}
std::string Name()
{
return _name;
}
void Send(int cmd)
{
::write(_wfd, &cmd, sizeof(cmd));
}
void Close()
{
::close(_wfd);
}
pid_t Id()
{
return _who;
}
~Channel()
{
}
private:
int _wfd;
std::string _name;
pid_t _who;
};
void Worker()
{
while (true)
{
int cmd = 0;
ssize_t n = ::read(0, &cmd, sizeof(cmd));
if (n == sizeof(cmd))
{
tm.Excute(cmd);
}
else if (n == 0)
{
std::cout << "pid: " << getpid() << " quit..." << std::endl;
break;
}
else
{
}
}
}
// channels : 输出型参数
// work_t work: 回调
int InitProcessPool(const int& processnum, std::vector<Channel>& channels, work_t work)
{
// 2. 创建指定个数个进程
for (int i = 0; i < processnum; i++)
{
// 1. 先有管道
int pipefd[2] = {0};
int n = pipe(pipefd);
if (n < 0)
{
return PipeError;
}
// 2. 创建进程
pid_t id = fork();
if (id < 0)
{
return ForkError;
}
// 3. 建立通信信道
if (id == 0)
{
::close(pipefd[1]); // read
// child
dup2(pipefd[0], 0);
work();
::exit(0);
}
// 父进程执行
::close(pipefd[0]); // write
channels.emplace_back(pipefd[1], id);
// Channel ch(pipefd[1], id);
// channels.push_back(ch);
}
return OK;
}
void DispatchTask(std::vector<Channel>& channels)
{
int who = 0;
// 2. 派发任务
int num = 20;
while (num--)
{
// a. 选择一个任务,整数
int task = tm.SelectTask();
// b. 选择一个子进程channel
Channel& curr = channels[who++];
who %= channels.size();
std::cout << "######################" << std::endl;
std::cout << "send " << task << " to " << curr.Name() << ", 任务还剩: " << num << std::endl;
std::cout << "######################" << std::endl;
// c. 派发任务
curr.Send(task);
sleep(1);
}
}
void CleanProcessPool(std::vector<Channel>& channels)
{
for (auto& c : channels)
{
c.Close();
}
for (auto& c : channels)
{
pid_t rid = ::waitpid(c.Id(), nullptr, 0);
if (rid > 0)
{
std::cout << "child " << rid << " wait ... success" << std::endl;
}
}
}
// 我们自己就是master
int main(int argc, char *argv[])
{
if (argc != 2)
{
Usage(argv[0]);
return UsageError;
}
int num = std::stoi(argv[1]);
std::vector<Channel> channels;
// 1. 初始化进程池
InitProcessPool(num, channels, Worker);
// 2. 派发任务
DispatchTask(channels);
// 3. 退出进程池
CleanProcessPool(channels);
return 0;
}
gsm@VM-4-3-ubuntu:~/linux/112/lesson21/processpool$ ll
total 20
drwxrwxr-x 2 gsm gsm 4096 Dec 16 12:17 ./
drwxrwxr-x 4 gsm gsm 4096 Dec 15 22:37 ../
-rw-rw-r-- 1 gsm gsm 277 Dec 15 23:02 Makefile
-rw-rw-r-- 1 gsm gsm 3701 Dec 16 15:47 processpool.cc
-rw-rw-r-- 1 gsm gsm 1058 Dec 16 15:03 Task.hpp
gsm@VM-4-3-ubuntu:~/linux/112/lesson21/processpool$ make
g++ -c -Wall -std=c++11 processpool.cc
g++ -o processpool processpool.o
gsm@VM-4-3-ubuntu:~/linux/112/lesson21/processpool$ ./processpool 10
######################
send 0 to Channel-4-1234935, 任务还剩: 19
######################
我是下载任务..., pid: 1234935
######################
send 0 to Channel-5-1234936, 任务还剩: 18
######################
我是下载任务..., pid: 1234936
######################
send 1 to Channel-6-1234937, 任务还剩: 17
######################
我是日志任务..., pid: 1234937
######################
send 2 to Channel-7-1234938, 任务还剩: 16
######################
我是数据库同步任务..., pid: 1234938
######################
send 1 to Channel-8-1234939, 任务还剩: 15
######################
我是日志任务..., pid: 1234939
######################
send 0 to Channel-9-1234940, 任务还剩: 14
######################
我是下载任务..., pid: 1234940
######################
send 2 to Channel-10-1234941, 任务还剩: 13
######################
我是数据库同步任务..., pid: 1234941
######################
send 2 to Channel-11-1234942, 任务还剩: 12
######################
我是数据库同步任务..., pid: 1234942
######################
send 1 to Channel-12-1234943, 任务还剩: 11
######################
我是日志任务..., pid: 1234943
######################
send 1 to Channel-13-1234944, 任务还剩: 10
######################
我是日志任务..., pid: 1234944
######################
send 1 to Channel-4-1234935, 任务还剩: 9
######################
我是日志任务..., pid: 1234935
######################
send 2 to Channel-5-1234936, 任务还剩: 8
######################
我是数据库同步任务..., pid: 1234936
######################
send 2 to Channel-6-1234937, 任务还剩: 7
######################
我是数据库同步任务..., pid: 1234937
######################
send 2 to Channel-7-1234938, 任务还剩: 6
######################
我是数据库同步任务..., pid: 1234938
######################
send 2 to Channel-8-1234939, 任务还剩: 5
######################
我是数据库同步任务..., pid: 1234939
######################
send 0 to Channel-9-1234940, 任务还剩: 4
######################
我是下载任务..., pid: 1234940
######################
send 0 to Channel-10-1234941, 任务还剩: 3
######################
我是下载任务..., pid: 1234941
######################
send 2 to Channel-11-1234942, 任务还剩: 2
######################
我是数据库同步任务..., pid: 1234942
######################
send 2 to Channel-12-1234943, 任务还剩: 1
######################
我是数据库同步任务..., pid: 1234943
######################
send 0 to Channel-13-1234944, 任务还剩: 0
######################
我是下载任务..., pid: 1234944
pid: 1234944 quit...
pid: 1234943 quit...
pid: 1234942 quit...
pid: 1234941 quit...
pid: 1234940 quit...
pid: 1234939 quit...
pid: 1234938 quit...
pid: 1234937 quit...
pid: 1234936 quit...
pid: 1234935 quit...
child 1234935 wait ... success
child 1234936 wait ... success
child 1234937 wait ... success
child 1234938 wait ... success
child 1234939 wait ... success
child 1234940 wait ... success
child 1234941 wait ... success
child 1234942 wait ... success
child 1234943 wait ... success
child 1234944 wait ... success
gsm@VM-4-3-ubuntu:~$ while :; do ps ajx | grep processpool; sleep 1; done
1214627 1234929 1234928 1214627 pts/1 1234928 S+ 1002 0:00 grep --color=auto processpool
1214627 1234932 1234931 1214627 pts/1 1234931 S+ 1002 0:00 grep --color=auto processpool
1229741 1234934 1234934 1229741 pts/0 1234934 S+ 1002 0:00 ./processpool 10
1234934 1234935 1234934 1229741 pts/0 1234934 S+ 1002 0:00 ./processpool 10
1234934 1234936 1234934 1229741 pts/0 1234934 S+ 1002 0:00 ./processpool 10
1234934 1234937 1234934 1229741 pts/0 1234934 S+ 1002 0:00 ./processpool 10
1234934 1234938 1234934 1229741 pts/0 1234934 S+ 1002 0:00 ./processpool 10
1234934 1234939 1234934 1229741 pts/0 1234934 S+ 1002 0:00 ./processpool 10
1234934 1234940 1234934 1229741 pts/0 1234934 S+ 1002 0:00 ./processpool 10
1234934 1234941 1234934 1229741 pts/0 1234934 S+ 1002 0:00 ./processpool 10
1234934 1234942 1234934 1229741 pts/0 1234934 S+ 1002 0:00 ./processpool 10
1234934 1234943 1234934 1229741 pts/0 1234934 S+ 1002 0:00 ./processpool 10
1234934 1234944 1234934 1229741 pts/0 1234934 S+ 1002 0:00 ./processpool 10
1214627 1234947 1234946 1214627 pts/1 1234946 S+ 1002 0:00 grep --color=auto processpool
1229741 1234934 1234934 1229741 pts/0 1234934 S+ 1002 0:00 ./processpool 10
1234934 1234935 1234934 1229741 pts/0 1234934 S+ 1002 0:00 ./processpool 10
1234934 1234936 1234934 1229741 pts/0 1234934 S+ 1002 0:00 ./processpool 10
1234934 1234937 1234934 1229741 pts/0 1234934 S+ 1002 0:00 ./processpool 10
1234934 1234938 1234934 1229741 pts/0 1234934 S+ 1002 0:00 ./processpool 10
1234934 1234939 1234934 1229741 pts/0 1234934 S+ 1002 0:00 ./processpool 10
1234934 1234940 1234934 1229741 pts/0 1234934 S+ 1002 0:00 ./processpool 10
1234934 1234941 1234934 1229741 pts/0 1234934 S+ 1002 0:00 ./processpool 10
1234934 1234942 1234934 1229741 pts/0 1234934 S+ 1002 0:00 ./processpool 10
1234934 1234943 1234934 1229741 pts/0 1234934 S+ 1002 0:00 ./processpool 10
1234934 1234944 1234934 1229741 pts/0 1234934 S+ 1002 0:00 ./processpool 10
1214627 1235075 1235074 1214627 pts/1 1235074 S+ 1002 0:00 grep --color=auto processpool
//中间这些都一样,就省略了
1229741 1234934 1234934 1229741 pts/0 1234934 S+ 1002 0:00 ./processpool 10
1234934 1234935 1234934 1229741 pts/0 1234934 S+ 1002 0:00 ./processpool 10
1234934 1234936 1234934 1229741 pts/0 1234934 S+ 1002 0:00 ./processpool 10
1234934 1234937 1234934 1229741 pts/0 1234934 S+ 1002 0:00 ./processpool 10
1234934 1234938 1234934 1229741 pts/0 1234934 S+ 1002 0:00 ./processpool 10
1234934 1234939 1234934 1229741 pts/0 1234934 S+ 1002 0:00 ./processpool 10
1234934 1234940 1234934 1229741 pts/0 1234934 S+ 1002 0:00 ./processpool 10
1234934 1234941 1234934 1229741 pts/0 1234934 S+ 1002 0:00 ./processpool 10
1234934 1234942 1234934 1229741 pts/0 1234934 S+ 1002 0:00 ./processpool 10
1234934 1234943 1234934 1229741 pts/0 1234934 S+ 1002 0:00 ./processpool 10
1234934 1234944 1234934 1229741 pts/0 1234934 S+ 1002 0:00 ./processpool 10
1214627 1235082 1235081 1214627 pts/1 1235081 S+ 1002 0:00 grep --color=auto processpool
1229741 1234934 1234934 1229741 pts/0 1234934 S+ 1002 0:00 ./processpool 10
1234934 1234935 1234934 1229741 pts/0 1234934 S+ 1002 0:00 ./processpool 10
1234934 1234936 1234934 1229741 pts/0 1234934 S+ 1002 0:00 ./processpool 10
1234934 1234937 1234934 1229741 pts/0 1234934 S+ 1002 0:00 ./processpool 10
1234934 1234938 1234934 1229741 pts/0 1234934 S+ 1002 0:00 ./processpool 10
1234934 1234939 1234934 1229741 pts/0 1234934 S+ 1002 0:00 ./processpool 10
1234934 1234940 1234934 1229741 pts/0 1234934 S+ 1002 0:00 ./processpool 10
1234934 1234941 1234934 1229741 pts/0 1234934 S+ 1002 0:00 ./processpool 10
1234934 1234942 1234934 1229741 pts/0 1234934 S+ 1002 0:00 ./processpool 10
1234934 1234943 1234934 1229741 pts/0 1234934 S+ 1002 0:00 ./processpool 10
1234934 1234944 1234934 1229741 pts/0 1234934 S+ 1002 0:00 ./processpool 10
1214627 1235092 1235091 1214627 pts/1 1235091 S+ 1002 0:00 grep --color=auto processpool
1214627 1235096 1235095 1214627 pts/1 1235095 S+ 1002 0:00 grep --color=auto processpool
1214627 1235101 1235100 1214627 pts/1 1235100 S+ 1002 0:00 grep --color=auto processpool
^C

优化一下上面的代码:
cpp
//Channel.hpp
#ifndef __CHANNEL_HPP__
#define __CHANNEL_HPP__
#include <iostream>
#include <string>
#include <unistd.h>
// 先描述
class Channel
{
public:
Channel(int wfd, pid_t who)
: _wfd(wfd)
, _who(who)
{
// Channel-3-1234
_name = "Channel-" + std::to_string(wfd) + "-" + std::to_string(who);
}
std::string Name()
{
return _name;
}
void Send(int cmd)
{
::write(_wfd, &cmd, sizeof(cmd));
}
void Close()
{
::close(_wfd);
}
pid_t Id()
{
return _who;
}
~Channel()
{
}
private:
int _wfd;
std::string _name;
pid_t _who;
};
#endif
//Task.hpp
#pragma once
#include <iostream>
#include <unordered_map>
#include <functional>
#include <ctime>
#include <sys/types.h>
#include <unistd.h>
using task_t = std::function<void()>;
void DownLoad()
{
std::cout << "我是下载任务..., pid: " << getpid() << std::endl;
}
void Log()
{
std::cout << "我是日志任务..., pid: " << getpid() << std::endl;
}
void Sql()
{
std::cout << "我是数据库同步任务..., pid: " << getpid() << std::endl;
}
static int number = 0;
class TaskManager
{
public:
TaskManager()
{
srand(time(nullptr));
InsertTask(DownLoad);
InsertTask(Log);
InsertTask(Sql);
}
void InsertTask(task_t t)
{
_tasks[number++] = t;
}
int SelectTask()
{
return rand() % number;
}
void Excute(int number)
{
if (_tasks.find(number) == _tasks.end())
{
return;
}
_tasks[number]();
}
~TaskManager()
{
}
private:
std::unordered_map<int, task_t> _tasks;
};
TaskManager tm;
void Worker()
{
while (true)
{
int cmd = 0;
ssize_t n = ::read(0, &cmd, sizeof(cmd));
if (n == sizeof(cmd))
{
tm.Excute(cmd);
}
else if (n == 0)
{
std::cout << "pid: " << getpid() << " quit..." << std::endl;
break;
}
else
{
}
}
}
//ProcessPool.hpp
#include <iostream>
#include <string>
#include <vector>
#include <cstdlib>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <functional>
#include "Task.hpp"
#include "Channel.hpp"
// const int num = 5;
// typedef std::function<void()> work_t;
using work_t = std::function<void()>;
enum
{
OK = 0,
UsageError,
PipeError,
ForkError
};
class ProcessPool
{
public:
ProcessPool(int n, work_t w)
: _processnum(n)
, _work(w)
{
}
// channels : 输出型参数
// work_t work: 回调
int InitProcessPool()
{
// 2. 创建指定个数个进程
for (int i = 0; i < _processnum; i++)
{
// 1. 先有管道
int pipefd[2] = {0};
int n = pipe(pipefd);
if (n < 0)
{
return PipeError;
}
// 2. 创建进程
pid_t id = fork();
if (id < 0)
{
return ForkError;
}
// 3. 建立通信信道
if (id == 0)
{
::close(pipefd[1]); // read
// child
std::cout << "debug: " << pipefd[0] << std::endl; // 3
dup2(pipefd[0], 0);
_work();
::exit(0);
}
// 父进程执行
::close(pipefd[0]); // write
_channels.emplace_back(pipefd[1], id);
// Channel ch(pipefd[1], id);
// channels.push_back(ch);
}
return OK;
}
void DispatchTask()
{
int who = 0;
// 2. 派发任务
int num = 20;
while (num--)
{
// a. 选择一个任务,整数
int task = tm.SelectTask();
// b. 选择一个子进程channel
Channel& curr = _channels[who++];
who %= _channels.size();
std::cout << "######################" << std::endl;
std::cout << "send " << task << " to " << curr.Name() << ", 任务还剩: " << num << std::endl;
std::cout << "######################" << std::endl;
// c. 派发任务
curr.Send(task);
sleep(1);
}
}
void CleanProcessPool()
{
// version 2
// 如果关闭写端和等待子进程写在一个循环里,必须从最后一个开始关
// 如果从第一个开始关程序会卡住,原因见原理图
for (int i = _channels.size() - 1; i >= 0; i--)
{
_channels[i].Close();
pid_t rid = ::waitpid(_channels[i].Id(), nullptr, 0);
if (rid > 0)
{
std::cout << "child " << rid << " wait ... success" << std::endl;
}
}
// version 1
// for (auto& c : _channels)
// {
// c.Close();
// }
// for (auto& c : _channels)
// {
// pid_t rid = ::waitpid(c.Id(), nullptr, 0);
// if (rid > 0)
// {
// std::cout << "child " << rid << " wait ... success" << std::endl;
// }
// }
}
private:
std::vector<Channel> _channels;
int _processnum;
work_t _work;
};
//Main.cc
#include "ProcessPool.hpp"
#include "Task.hpp"
void Usage(std::string proc)
{
std::cout << "Usage: " << proc << " process-num" << std::endl;
}
// 我们自己就是master
int main(int argc, char *argv[])
{
if (argc != 2)
{
Usage(argv[0]);
return UsageError;
}
int num = std::stoi(argv[1]);
ProcessPool* pp = new ProcessPool(num, Worker);
// 1. 初始化进程池
pp->InitProcessPool();
// 2. 派发任务
pp->DispatchTask();
// 3. 退出进程池
pp->CleanProcessPool();
delete pp;
return 0;
}
如果要写成version 3的样子,代码需要这样修改:
cpp
//Channel.hpp
#ifndef __CHANNEL_HPP__
#define __CHANNEL_HPP__
#include <iostream>
#include <string>
#include <unistd.h>
// 先描述
class Channel
{
public:
Channel(int wfd, pid_t who)
: _wfd(wfd)
, _who(who)
{
// Channel-3-1234
_name = "Channel-" + std::to_string(wfd) + "-" + std::to_string(who);
}
std::string Name()
{
return _name;
}
void Send(int cmd)
{
::write(_wfd, &cmd, sizeof(cmd));
}
void Close()
{
::close(_wfd);
}
pid_t Id()
{
return _who;
}
int wFd()
{
return _wfd;
}
~Channel()
{
}
private:
int _wfd;
std::string _name;
pid_t _who;
};
#endif
//ProcessPool.hpp
#include <iostream>
#include <string>
#include <vector>
#include <cstdlib>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <functional>
#include "Task.hpp"
#include "Channel.hpp"
// const int num = 5;
// typedef std::function<void()> work_t;
using work_t = std::function<void()>;
enum
{
OK = 0,
UsageError,
PipeError,
ForkError
};
class ProcessPool
{
public:
ProcessPool(int n, work_t w)
: _processnum(n)
, _work(w)
{
}
// channels : 输出型参数
// work_t work: 回调
int InitProcessPool()
{
// 2. 创建指定个数个进程
for (int i = 0; i < _processnum; i++)
{
// 1. 先有管道
int pipefd[2] = {0};
int n = pipe(pipefd);
if (n < 0)
{
return PipeError;
}
// 2. 创建进程
pid_t id = fork();
if (id < 0)
{
return ForkError;
}
// 3. 建立通信信道
if (id == 0)
{
// 关闭历史wfd
std::cout << getpid() << ", child close history fd: ";
for (auto& c : _channels)
{
std::cout << c.wFd() << " ";
c.Close();
}
std::cout << " over" << std::endl;
::close(pipefd[1]); // read
// child
std::cout << "debug: " << pipefd[0] << std::endl; // 3
dup2(pipefd[0], 0);
_work();
::exit(0);
}
// 父进程执行
::close(pipefd[0]); // write
_channels.emplace_back(pipefd[1], id);
// Channel ch(pipefd[1], id);
// channels.push_back(ch);
}
return OK;
}
void DispatchTask()
{
int who = 0;
// 2. 派发任务
int num = 20;
while (num--)
{
// a. 选择一个任务,整数
int task = tm.SelectTask();
// b. 选择一个子进程channel
Channel& curr = _channels[who++];
who %= _channels.size();
std::cout << "######################" << std::endl;
std::cout << "send " << task << " to " << curr.Name() << ", 任务还剩: " << num << std::endl;
std::cout << "######################" << std::endl;
// c. 派发任务
curr.Send(task);
sleep(1);
}
}
void CleanProcessPool()
{
// version 3
for (auto& c : _channels)
{
c.Close();
pid_t rid = ::waitpid(c.Id(), nullptr, 0);
if (rid > 0)
{
std::cout << "child " << rid << " wait ... success" << std::endl;
}
}
// version 2
// 如果关闭写端和等待子进程写在一个循环里,必须从最后一个开始关
// 如果从第一个开始关程序会卡住,原因见原理图
// for (int i = _channels.size() - 1; i >= 0; i--)
// {
// _channels[i].Close();
// pid_t rid = ::waitpid(_channels[i].Id(), nullptr, 0);
// if (rid > 0)
// {
// std::cout << "child " << rid << " wait ... success" << std::endl;
// }
// }
// version 1
// for (auto& c : _channels)
// {
// c.Close();
// }
// for (auto& c : _channels)
// {
// pid_t rid = ::waitpid(c.Id(), nullptr, 0);
// if (rid > 0)
// {
// std::cout << "child " << rid << " wait ... success" << std::endl;
// }
// }
}
private:
std::vector<Channel> _channels;
int _processnum;
work_t _work;
};
4. 命名管道

c
gsm@VM-4-3-ubuntu:~/linux/112/lesson21$ ll
total 16
drwxrwxr-x 4 gsm gsm 4096 Dec 15 22:37 ./
drwxrwxr-x 20 gsm gsm 4096 Dec 13 22:38 ../
drwxrwxr-x 2 gsm gsm 4096 Dec 15 22:37 pipe/
drwxrwxr-x 2 gsm gsm 4096 Dec 16 18:20 processpool/
gsm@VM-4-3-ubuntu:~/linux/112/lesson21$ man mkfifo
gsm@VM-4-3-ubuntu:~/linux/112/lesson21$ mkfifo fifo
gsm@VM-4-3-ubuntu:~/linux/112/lesson21$ ll
total 16
drwxrwxr-x 4 gsm gsm 4096 Dec 17 15:28 ./
drwxrwxr-x 20 gsm gsm 4096 Dec 13 22:38 ../
prw-rw-r-- 1 gsm gsm 0 Dec 17 15:28 fifo|
drwxrwxr-x 2 gsm gsm 4096 Dec 15 22:37 pipe/
drwxrwxr-x 2 gsm gsm 4096 Dec 16 18:20 processpool/
gsm@VM-4-3-ubuntu:~/linux/112/lesson21$ echo "hello world" >fifo
gsm@VM-4-3-ubuntu:~/linux/112/lesson21$ ll
total 16
drwxrwxr-x 4 gsm gsm 4096 Dec 17 15:28 ./
drwxrwxr-x 20 gsm gsm 4096 Dec 13 22:38 ../
prw-rw-r-- 1 gsm gsm 0 Dec 17 15:36 fifo|
drwxrwxr-x 2 gsm gsm 4096 Dec 15 22:37 pipe/
drwxrwxr-x 2 gsm gsm 4096 Dec 16 18:20 processpool/
gsm@VM-4-3-ubuntu:~/linux/112/lesson21$ man 3 mkfifo
//打开另一个Xshell
gsm@VM-4-3-ubuntu:~/linux/112/lesson21$ ll
total 16
drwxrwxr-x 4 gsm gsm 4096 Dec 17 15:28 ./
drwxrwxr-x 20 gsm gsm 4096 Dec 13 22:38 ../
prw-rw-r-- 1 gsm gsm 0 Dec 17 15:28 fifo|
drwxrwxr-x 2 gsm gsm 4096 Dec 15 22:37 pipe/
drwxrwxr-x 2 gsm gsm 4096 Dec 16 18:20 processpool/
gsm@VM-4-3-ubuntu:~/linux/112/lesson21$ cat < fifo
hello world

cpp
//Makefile
SERVER=server
CLIENT=client
CC=g++
SERVER_SRC=Server.cc
CLIENT_SRC=Client.cc
.PHONY:all
all:$(SERVER) $(CLIENT)
$(SERVER):$(SERVER_SRC)
$(CC) -o $@ $^ -std=c++11
$(CLIENT):$(CLIENT_SRC)
$(CC) -o $@ $^ -std=c++11
.PHONY:clean
clean:
rm -f $(SERVER) $(CLIENT)
gsm@VM-4-3-ubuntu:~/linux/112/lesson22$ ll
total 28
drwxrwxr-x 2 gsm gsm 4096 Dec 17 17:02 ./
drwxrwxr-x 21 gsm gsm 4096 Dec 17 16:58 ../
-rw-rw-r-- 1 gsm gsm 126 Dec 17 17:26 Client.cc
-rw-rw-r-- 1 gsm gsm 32 Dec 17 17:04 Client.hpp
-rw-rw-r-- 1 gsm gsm 263 Dec 17 17:56 Makefile
-rw-rw-r-- 1 gsm gsm 126 Dec 17 17:25 Server.cc
-rw-rw-r-- 1 gsm gsm 32 Dec 17 17:04 Server.hpp
gsm@VM-4-3-ubuntu:~/linux/112/lesson22$ make
g++ -o server Server.cc -std=c++11
g++ -o client Client.cc -std=c++11
gsm@VM-4-3-ubuntu:~/linux/112/lesson22$ ll
total 68
drwxrwxr-x 2 gsm gsm 4096 Dec 17 17:56 ./
drwxrwxr-x 21 gsm gsm 4096 Dec 17 16:58 ../
-rwxrwxr-x 1 gsm gsm 16576 Dec 17 17:56 client*
-rw-rw-r-- 1 gsm gsm 126 Dec 17 17:26 Client.cc
-rw-rw-r-- 1 gsm gsm 32 Dec 17 17:04 Client.hpp
-rw-rw-r-- 1 gsm gsm 263 Dec 17 17:56 Makefile
-rwxrwxr-x 1 gsm gsm 16576 Dec 17 17:56 server*
-rw-rw-r-- 1 gsm gsm 126 Dec 17 17:25 Server.cc
-rw-rw-r-- 1 gsm gsm 32 Dec 17 17:04 Server.hpp
gsm@VM-4-3-ubuntu:~/linux/112/lesson22$ ./server
Server
gsm@VM-4-3-ubuntu:~/linux/112/lesson22$ ./client
Client
gsm@VM-4-3-ubuntu:~/linux/112/lesson22$ make clean
rm -f server client
gsm@VM-4-3-ubuntu:~/linux/112/lesson22$ ll
total 28
drwxrwxr-x 2 gsm gsm 4096 Dec 17 17:57 ./
drwxrwxr-x 21 gsm gsm 4096 Dec 17 16:58 ../
-rw-rw-r-- 1 gsm gsm 126 Dec 17 17:26 Client.cc
-rw-rw-r-- 1 gsm gsm 32 Dec 17 17:04 Client.hpp
-rw-rw-r-- 1 gsm gsm 263 Dec 17 17:56 Makefile
-rw-rw-r-- 1 gsm gsm 126 Dec 17 17:25 Server.cc
-rw-rw-r-- 1 gsm gsm 32 Dec 17 17:04 Server.hpp
cpp
//Comm.hpp
#pragma once
#include <iostream>
#include <string>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
const std::string gpipeFile = "./fifo";
const mode_t gmode = 0600;
const int gdefaultfd = -1;
const int gsize = 1024;
//Server.hpp
#pragma once
#include <iostream>
#include "Comm.hpp"
class Init
{
public:
Init()
{
umask(0);
int n = ::mkfifo(gpipeFile.c_str(), gmode);
if (n < 0)
{
std::cerr << "mkfifo error" << std::endl;
return;
}
std::cout << "mkfifo success" << std::endl;
}
~Init()
{
int n = ::unlink(gpipeFile.c_str());
if (n < 0)
{
std::cerr << "unlink error" << std::endl;
return;
}
std::cout << "unlink success" << std::endl;
}
};
Init init;
class Server
{
public:
Server()
: _fd(gdefaultfd)
{
}
bool OpenPipe()
{
_fd = ::open(gpipeFile.c_str(), O_RDONLY);
if (_fd < 0)
{
std::cerr << "open error" << std::endl;
return false;
}
return true;
}
// std::string* : 输出型参数
// const std::string& : 输入型参数
// std::string& : 输入输出型参数
int RecvPipe(std::string* out)
{
char buffer[gsize];
ssize_t n = ::read(_fd, buffer, sizeof(buffer) - 1);
if (n > 0)
{
buffer[n] = 0;
*out = buffer;
}
return n;
}
void ClosePipe()
{
if (_fd >= 0)
{
::close(_fd);
}
}
~Server()
{
}
private:
int _fd;
};
//Server.cc
#include "Server.hpp"
#include <iostream>
int main()
{
Server server;
server.OpenPipe();
std::string message;
while (true)
{
server.RecvPipe(&message);
std::cout << "client Say# " << message << std::endl;
}
server.ClosePipe();
return 0;
}
//Client.hpp
#pragma once
#include <iostream>
#include "Comm.hpp"
class Client
{
public:
Client()
: _fd(gdefaultfd)
{
}
bool OpenPipe()
{
_fd = ::open(gpipeFile.c_str(), O_WRONLY);
if (_fd < 0)
{
std::cerr << "open error" << std::endl;
return false;
}
return true;
}
// std::string* : 输出型参数
// const std::string& : 输入型参数
// std::string& : 输入输出型参数
int SendPipe(std::string& in)
{
return ::write(_fd, in.c_str(), in.size());
}
void ClosePipe()
{
if (_fd >= 0)
{
::close(_fd);
}
}
~Client()
{
}
private:
int _fd;
};
//Client.cc
#include "Client.hpp"
#include <iostream>
int main()
{
Client client;
client.OpenPipe();
std::string message;
while (true)
{
std::cout << "Please Enter# ";
std::getline(std::cin, message);
client.SendPipe(message);
}
client.ClosePipe();
return 0;
}
gsm@VM-4-3-ubuntu:~/linux/112/lesson22$ ll
total 32
drwxrwxr-x 2 gsm gsm 4096 Dec 18 00:41 ./
drwxrwxr-x 21 gsm gsm 4096 Dec 17 16:58 ../
-rw-rw-r-- 1 gsm gsm 309 Dec 18 00:29 Client.cc
-rw-rw-r-- 1 gsm gsm 735 Dec 18 00:18 Client.hpp
-rw-rw-r-- 1 gsm gsm 254 Dec 17 23:47 Comm.hpp
-rw-rw-r-- 1 gsm gsm 263 Dec 17 17:56 Makefile
-rw-rw-r-- 1 gsm gsm 291 Dec 18 00:24 Server.cc
-rw-rw-r-- 1 gsm gsm 1420 Dec 18 00:04 Server.hpp
gsm@VM-4-3-ubuntu:~/linux/112/lesson22$ make
g++ -o server Server.cc -std=c++11
g++ -o client Client.cc -std=c++11
gsm@VM-4-3-ubuntu:~/linux/112/lesson22$ ll
total 72
drwxrwxr-x 2 gsm gsm 4096 Dec 18 00:41 ./
drwxrwxr-x 21 gsm gsm 4096 Dec 17 16:58 ../
-rwxrwxr-x 1 gsm gsm 18240 Dec 18 00:41 client*
-rw-rw-r-- 1 gsm gsm 309 Dec 18 00:29 Client.cc
-rw-rw-r-- 1 gsm gsm 735 Dec 18 00:18 Client.hpp
-rw-rw-r-- 1 gsm gsm 254 Dec 17 23:47 Comm.hpp
-rw-rw-r-- 1 gsm gsm 263 Dec 17 17:56 Makefile
-rwxrwxr-x 1 gsm gsm 18480 Dec 18 00:41 server*
-rw-rw-r-- 1 gsm gsm 291 Dec 18 00:24 Server.cc
-rw-rw-r-- 1 gsm gsm 1420 Dec 18 00:04 Server.hpp
gsm@VM-4-3-ubuntu:~/linux/112/lesson22$ ./server
mkfifo success
client Say# nihao
client Say# good
client Say# byebye
client Say# aaaaaaa
client Say# bbbbbbbb
client Say# cccccc
client Say# ddddddddddd
client Say# adsf
client Say# asdf
client Say# asdf
client Say# asdf
client Say# asf
client Say# fasd
client Say# fad
client Say# fasd
client Say# fasd
client Say# fasd
client Say# fasd
//另一个Xshell
gsm@VM-4-3-ubuntu:~/linux/112/lesson22$ ll
total 72
drwxrwxr-x 2 gsm gsm 4096 Dec 18 00:41 ./
drwxrwxr-x 21 gsm gsm 4096 Dec 17 16:58 ../
-rwxrwxr-x 1 gsm gsm 18240 Dec 18 00:41 client*
-rw-rw-r-- 1 gsm gsm 309 Dec 18 00:29 Client.cc
-rw-rw-r-- 1 gsm gsm 735 Dec 18 00:18 Client.hpp
-rw-rw-r-- 1 gsm gsm 254 Dec 17 23:47 Comm.hpp
-rw-rw-r-- 1 gsm gsm 263 Dec 17 17:56 Makefile
-rwxrwxr-x 1 gsm gsm 18480 Dec 18 00:41 server*
-rw-rw-r-- 1 gsm gsm 291 Dec 18 00:24 Server.cc
-rw-rw-r-- 1 gsm gsm 1420 Dec 18 00:04 Server.hpp
gsm@VM-4-3-ubuntu:~/linux/112/lesson22$ ./client
Please Enter# nihao
Please Enter# good
Please Enter# byebye
Please Enter# aaaaaaa
Please Enter# bbbbbbbb
Please Enter# cccccc
Please Enter# ddddddddddd
Please Enter# adsf
Please Enter# asdf
Please Enter# asdf
Please Enter# asdf
Please Enter# asf
Please Enter# fasd
Please Enter# fad
Please Enter# fasd
Please Enter# fasd
Please Enter# fasd
Please Enter# fasd
Please Enter#
这里会有一个问题:如果客户端退出了,服务端开始死循环打印消息,应该这样修改:
cpp
//Server.cc
#include "Server.hpp"
#include <iostream>
int main()
{
Server server;
server.OpenPipe();
std::string message;
while (true)
{
if (server.RecvPipe(&message) > 0)
{
std::cout << "client Say# " << message << std::endl;
}
else
{
break;
}
}
std::cout << "client quit, me too!" << std::endl;
server.ClosePipe();
return 0;
}
gsm@VM-4-3-ubuntu:~/linux/112/lesson22$ ll
total 32
drwxrwxr-x 2 gsm gsm 4096 Dec 18 00:47 ./
drwxrwxr-x 21 gsm gsm 4096 Dec 17 16:58 ../
-rw-rw-r-- 1 gsm gsm 309 Dec 18 00:29 Client.cc
-rw-rw-r-- 1 gsm gsm 735 Dec 18 00:18 Client.hpp
-rw-rw-r-- 1 gsm gsm 254 Dec 17 23:47 Comm.hpp
-rw-rw-r-- 1 gsm gsm 263 Dec 17 17:56 Makefile
-rw-rw-r-- 1 gsm gsm 430 Dec 18 12:30 Server.cc
-rw-rw-r-- 1 gsm gsm 1420 Dec 18 00:04 Server.hpp
gsm@VM-4-3-ubuntu:~/linux/112/lesson22$ make
g++ -o server Server.cc -std=c++11
g++ -o client Client.cc -std=c++11
gsm@VM-4-3-ubuntu:~/linux/112/lesson22$ ll
total 72
drwxrwxr-x 2 gsm gsm 4096 Dec 18 12:31 ./
drwxrwxr-x 21 gsm gsm 4096 Dec 17 16:58 ../
-rwxrwxr-x 1 gsm gsm 18240 Dec 18 12:31 client*
-rw-rw-r-- 1 gsm gsm 309 Dec 18 00:29 Client.cc
-rw-rw-r-- 1 gsm gsm 735 Dec 18 00:18 Client.hpp
-rw-rw-r-- 1 gsm gsm 254 Dec 17 23:47 Comm.hpp
-rw-rw-r-- 1 gsm gsm 263 Dec 17 17:56 Makefile
-rwxrwxr-x 1 gsm gsm 18568 Dec 18 12:31 server*
-rw-rw-r-- 1 gsm gsm 430 Dec 18 12:30 Server.cc
-rw-rw-r-- 1 gsm gsm 1420 Dec 18 00:04 Server.hpp
gsm@VM-4-3-ubuntu:~/linux/112/lesson22$ ./server
mkfifo success
client Say# ll
client Say# aa
client Say# bb
client Say# dd
client Say# ddddd
client Say# aaa aaa bbb
client quit, me too!
unlink success
gsm@VM-4-3-ubuntu:~/linux/112/lesson22$ ll
total 72
drwxrwxr-x 2 gsm gsm 4096 Dec 18 12:32 ./
drwxrwxr-x 21 gsm gsm 4096 Dec 17 16:58 ../
-rwxrwxr-x 1 gsm gsm 18240 Dec 18 12:31 client*
-rw-rw-r-- 1 gsm gsm 309 Dec 18 00:29 Client.cc
-rw-rw-r-- 1 gsm gsm 735 Dec 18 00:18 Client.hpp
-rw-rw-r-- 1 gsm gsm 254 Dec 17 23:47 Comm.hpp
-rw-rw-r-- 1 gsm gsm 263 Dec 17 17:56 Makefile
-rwxrwxr-x 1 gsm gsm 18568 Dec 18 12:31 server*
-rw-rw-r-- 1 gsm gsm 430 Dec 18 12:30 Server.cc
-rw-rw-r-- 1 gsm gsm 1420 Dec 18 00:04 Server.hpp
//另一个Xshell
gsm@VM-4-3-ubuntu:~/linux/112/lesson22$ ll
total 72
drwxrwxr-x 2 gsm gsm 4096 Dec 18 12:31 ./
drwxrwxr-x 21 gsm gsm 4096 Dec 17 16:58 ../
-rwxrwxr-x 1 gsm gsm 18240 Dec 18 12:31 client*
-rw-rw-r-- 1 gsm gsm 309 Dec 18 00:29 Client.cc
-rw-rw-r-- 1 gsm gsm 735 Dec 18 00:18 Client.hpp
-rw-rw-r-- 1 gsm gsm 254 Dec 17 23:47 Comm.hpp
-rw-rw-r-- 1 gsm gsm 263 Dec 17 17:56 Makefile
-rwxrwxr-x 1 gsm gsm 18568 Dec 18 12:31 server*
-rw-rw-r-- 1 gsm gsm 430 Dec 18 12:30 Server.cc
-rw-rw-r-- 1 gsm gsm 1420 Dec 18 00:04 Server.hpp
gsm@VM-4-3-ubuntu:~/linux/112/lesson22$ ./client
Please Enter# ll
Please Enter# aa
Please Enter# bb
Please Enter# dd
Please Enter# ddddd
Please Enter# aaa aaa bbb
Please Enter# ^C
优化一下代码:
cpp
//Comm.hpp
#pragma once
#include <iostream>
#include <string>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
const std::string gpipeFile = "./fifo";
const mode_t gmode = 0600;
const int gdefaultfd = -1;
const int gsize = 1024;
const int gForRead = O_RDONLY;
const int gForWrite = O_WRONLY;
int OpenPipe(int flag)
{
int fd = ::open(gpipeFile.c_str(), flag);
if (fd < 0)
{
std::cerr << "open error" << std::endl;
}
return fd;
}
void ClosePipeHelper(int fd)
{
if (fd >= 0)
{
::close(fd);
}
}
//Server.hpp
#pragma once
#include <iostream>
#include "Comm.hpp"
class Init
{
public:
Init()
{
umask(0);
int n = ::mkfifo(gpipeFile.c_str(), gmode);
if (n < 0)
{
std::cerr << "mkfifo error" << std::endl;
return;
}
std::cout << "mkfifo success" << std::endl;
}
~Init()
{
int n = ::unlink(gpipeFile.c_str());
if (n < 0)
{
std::cerr << "unlink error" << std::endl;
return;
}
std::cout << "unlink success" << std::endl;
}
};
Init init;
class Server
{
public:
Server()
: _fd(gdefaultfd)
{
}
bool OpenPipeForRead()
{
_fd = OpenPipe(gForRead);
if (_fd < 0)
{
return false;
}
return true;
}
// std::string* : 输出型参数
// const std::string& : 输入型参数
// std::string& : 输入输出型参数
int RecvPipe(std::string* out)
{
char buffer[gsize];
ssize_t n = ::read(_fd, buffer, sizeof(buffer) - 1);
if (n > 0)
{
buffer[n] = 0;
*out = buffer;
}
return n;
}
void ClosePipe()
{
ClosePipeHelper(_fd);
}
~Server()
{
}
private:
int _fd;
};
//Server.cc
#include "Server.hpp"
#include <iostream>
int main()
{
Server server;
server.OpenPipeForRead();
std::string message;
while (true)
{
if (server.RecvPipe(&message) > 0)
{
std::cout << "client Say# " << message << std::endl;
}
else
{
break;
}
}
std::cout << "client quit, me too!" << std::endl;
server.ClosePipe();
return 0;
}
//Client.hpp
#pragma once
#include <iostream>
#include "Comm.hpp"
class Client
{
public:
Client()
: _fd(gdefaultfd)
{
}
bool OpenPipeForWrite()
{
_fd = OpenPipe(gForWrite);
if (_fd < 0)
{
return false;
}
return true;
}
// std::string* : 输出型参数
// const std::string& : 输入型参数
// std::string& : 输入输出型参数
int SendPipe(std::string& in)
{
return ::write(_fd, in.c_str(), in.size());
}
void ClosePipe()
{
ClosePipeHelper(_fd);
}
~Client()
{
}
private:
int _fd;
};
//Client.cc
#include "Client.hpp"
#include <iostream>
int main()
{
Client client;
client.OpenPipeForWrite();
std::string message;
while (true)
{
std::cout << "Please Enter# ";
std::getline(std::cin, message);
client.SendPipe(message);
}
client.ClosePipe();
return 0;
}
gsm@VM-4-3-ubuntu:~/linux/112/lesson22$ ll
total 32
drwxrwxr-x 2 gsm gsm 4096 Dec 18 12:57 ./
drwxrwxr-x 21 gsm gsm 4096 Dec 17 16:58 ../
-rw-rw-r-- 1 gsm gsm 317 Dec 18 12:55 Client.cc
-rw-rw-r-- 1 gsm gsm 637 Dec 18 12:54 Client.hpp
-rw-rw-r-- 1 gsm gsm 568 Dec 18 12:52 Comm.hpp
-rw-rw-r-- 1 gsm gsm 263 Dec 17 17:56 Makefile
-rw-rw-r-- 1 gsm gsm 437 Dec 18 12:55 Server.cc
-rw-rw-r-- 1 gsm gsm 1321 Dec 18 12:54 Server.hpp
gsm@VM-4-3-ubuntu:~/linux/112/lesson22$ make
g++ -o server Server.cc -std=c++11
g++ -o client Client.cc -std=c++11
gsm@VM-4-3-ubuntu:~/linux/112/lesson22$ ./server
mkfifo success
client Say# nihao
client Say# agggod
client Say# adf
client Say# adf
client Say# adf
client Say# adf
client quit, me too!
unlink success
//另一个Xshell
gsm@VM-4-3-ubuntu:~/linux/112/lesson22$ ll
total 32
drwxrwxr-x 2 gsm gsm 4096 Dec 18 12:57 ./
drwxrwxr-x 21 gsm gsm 4096 Dec 17 16:58 ../
-rw-rw-r-- 1 gsm gsm 317 Dec 18 12:55 Client.cc
-rw-rw-r-- 1 gsm gsm 637 Dec 18 12:54 Client.hpp
-rw-rw-r-- 1 gsm gsm 568 Dec 18 12:52 Comm.hpp
-rw-rw-r-- 1 gsm gsm 263 Dec 17 17:56 Makefile
-rw-rw-r-- 1 gsm gsm 437 Dec 18 12:55 Server.cc
-rw-rw-r-- 1 gsm gsm 1321 Dec 18 12:54 Server.hpp
gsm@VM-4-3-ubuntu:~/linux/112/lesson22$ ./client
Please Enter# nihao
Please Enter# agggod
Please Enter# adf
Please Enter# adf
Please Enter# adf
Please Enter# adf
Please Enter# ^C
管道首次以读方式打开,曾经管道没有被人打开过,它会阻塞住,不是 写端关闭读端打开 的那种情况
cpp
//Comm.hpp
#pragma once
#include <iostream>
#include <string>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
const std::string gpipeFile = "./fifo";
const mode_t gmode = 0600;
const int gdefaultfd = -1;
const int gsize = 1024;
const int gForRead = O_RDONLY;
const int gForWrite = O_WRONLY;
int OpenPipe(int flag)
{
// 如果读端打开文件时,写端还没打开,读端对应的open就会阻塞
int fd = ::open(gpipeFile.c_str(), flag);
if (fd < 0)
{
std::cerr << "open error" << std::endl;
}
return fd;
}
void ClosePipeHelper(int fd)
{
if (fd >= 0)
{
::close(fd);
}
}
//Server.cc
#include "Server.hpp"
#include <iostream>
int main()
{
Server server;
std::cout << "pos 1" << std::endl;
server.OpenPipeForRead();
std::cout << "pos 2" << std::endl;
std::string message;
while (true)
{
if (server.RecvPipe(&message) > 0)
{
std::cout << "client Say# " << message << std::endl;
}
else
{
break;
}
std::cout << "pos 3" << std::endl;
}
std::cout << "client quit, me too!" << std::endl;
server.ClosePipe();
return 0;
}
gsm@VM-4-3-ubuntu:~/linux/112/lesson22$ ll
total 32
drwxrwxr-x 2 gsm gsm 4096 Dec 18 15:21 ./
drwxrwxr-x 21 gsm gsm 4096 Dec 17 16:58 ../
-rw-rw-r-- 1 gsm gsm 317 Dec 18 12:55 Client.cc
-rw-rw-r-- 1 gsm gsm 637 Dec 18 12:54 Client.hpp
-rw-rw-r-- 1 gsm gsm 658 Dec 18 15:49 Comm.hpp
-rw-rw-r-- 1 gsm gsm 263 Dec 17 17:56 Makefile
-rw-rw-r-- 1 gsm gsm 567 Dec 18 15:39 Server.cc
-rw-rw-r-- 1 gsm gsm 1321 Dec 18 12:54 Server.hpp
gsm@VM-4-3-ubuntu:~/linux/112/lesson22$ make
g++ -o server Server.cc -std=c++11
g++ -o client Client.cc -std=c++11
gsm@VM-4-3-ubuntu:~/linux/112/lesson22$ ./server
mkfifo success
pos 1