实现进程管理协同
fork()
pipe() 实现进程通信
每个进程各自有不同的用户地址空间,任何一个进程的全局变量在另一个进程中都看不到,所以进程之间要交换数据必须通过内核,在内核中开辟一块缓冲区,进程A把数据从用户空间拷到内核缓冲区,进程B再从内核缓冲区把数据读走,内核提供的这种机制称为进程间通信。
API函数的使用以及注意点
1 2
| #include <unistd.h> int pipe(int pipefd[2]);
|
参数说明:
- fd为文件描述符数组,其中fd[0]表示读端,fd[1] 表示写端
返回值:
注意点:
- 管道内
没有数据
时,读端(read)
发生 阻塞
,等待有效数据进行读取
- 管道容量被
数据填满
时,写端(write)发生阻塞
,等待进程将数据读走再进行写入
- 如果所有管道
写端对应的文件描述符被关闭
,read返回0
,但会将之前管道里的数据读完
- 如果所有管道的
读端对应的文件描述符被关闭
,write操作会产生信号,SIGPIPE
,进而导致write进程退出
- 当要写入的数据量不大于管道的容量(PIPE_BUF)时,linux将保证写入的原子性
- 当要写入的数据量大于管道容量(PIPE_BUF)时,linux将不再保证写入的原子性
fork子进程并使用pipe通信
>folded1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
| #include <unistd.h> #include <sys/types.h> #include <iostream> #include <string> #include <cstring> #include <sys/wait.h> using namespace std; int main() { int pipe_fd[2]; pid_t cpid; char buf;
if (pipe(pipe_fd) == -1) { perror("pipe"); }
for (int i = 0; i < 4; ++i) { cpid = fork(); if (cpid == -1) { perror("fork"); }
if (cpid == 0) { close(pipe_fd[0]);
string message = "Child " + to_string(getpid()) + " is sending a message to parent!\n"; write(pipe_fd[1], message.c_str(), message.length());
close(pipe_fd[1]); } else { } } close(pipe_fd[1]);
while (read(pipe_fd[0], &buf, 1) > 0) { write(STDOUT_FILENO, &buf, 1); }
close(pipe_fd[0]);
for (int i = 0; i < 4; ++i) { wait(NULL); }
return 0; }
|
shmget() shmat() shmdt() shmctl() 实现进程间数据同步
int shmget(key_t key, size_t size, int shmflg);
目的:用于创建新的共享内存段或访问一个已存在的共享内存段。
void *shmat(int shmid, const void *shmaddr, int shmflg);
目的:将共享内存段附加到调用进程的地址空间。
int shmdt(const void *shmaddr);
目的:将共享内存段从当前进程的地址空间分离。
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
目的:对共享内存段执行各种控制操作。
示例程序
./2.cpp:
>folded1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| #include <iostream> #include <sys/ipc.h> #include <sys/shm.h> #include <cstring> #include <unistd.h>
#define SHM_SIZE 512
int main() { key_t key = ftok("shmfile",65); int shmid = shmget(key, SHM_SIZE, 0666|IPC_CREAT); if (shmid == -1) { perror("shmget"); exit(1); }
char *data = (char*) shmat(shmid, (void*)0, 0); if (data == (char*)(-1)) { perror("shmat"); exit(1); }
std::cout << "Waiting for process B to write data...\n"; sleep(5);
std::cout << "Data read from shared memory: " << data << std::endl;
if (shmdt(data) == -1) { perror("shmdt"); exit(1); }
shmctl(shmid, IPC_RMID, NULL);
return 0; }
|
./2.1.cpp:
>folded1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| #include <iostream> #include <sys/ipc.h> #include <sys/shm.h> #include <cstring>
#define SHM_SIZE 512
int main() { key_t key = ftok("shmfile",65); int shmid = shmget(key, SHM_SIZE, 0666); if (shmid == -1) { perror("shmget"); exit(1); }
char *data = (char*) shmat(shmid, (void*)0, 0); if (data == (char*)(-1)) { perror("shmat"); exit(1); }
std::cout << "Writing to shared memory\n"; std::strncpy(data, "Hello from process B!", SHM_SIZE);
if (shmdt(data) == -1) { perror("shmdt"); exit(1); }
return 0; }
|