实验五 命名匿名管道通信

【实验软硬件环境】

Linux、Win11、GCC

【实验目的与内容】

学习使用命名匿名管道在多进程间建立通信。

建立父子进程,由父进程创建一个命名匿名管道,由子进程向 命名管道写入数据,由父进程从命名管道读取数据。

【实验程序及分析】

Windows下

父进程代码father.cpp
1
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 <windows.h>
#include <process.h>
#include <cstring>
#include <stdio.h>

int main() {
HANDLE hPipeRead;
HANDLE hPipeWrite = CreateNamedPipe(TEXT("\\\\.\\Pipe\\test_write"), PIPE_ACCESS_DUPLEX,//创建命名管道
PIPE_READMODE_BYTE | PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, 0, 0, NMPWAIT_WAIT_FOREVER, NULL);

STARTUPINFO si = {0};//si进程创建
ZeroMemory(&si, sizeof(STARTUPINFO));
PROCESS_INFORMATION pi = {0};
BOOL bSuccess = CreateProcess(TEXT("child.exe"), NULL, NULL, NULL, TRUE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi);//创建子进程

if (ConnectNamedPipe(hPipeWrite, NULL)) {
printf("Connected\n");
printf("Send signal? [Y/n]\n");
char ch;
scanf("%c",&ch);
if (ch == 'y' || ch == 'Y') {
DWORD dwWrite;
const char* ptr = "start";
if (!WriteFile(hPipeWrite, ptr, strlen(ptr), &dwWrite, NULL)) {
printf("ERROR\n");
}
printf("Signal sent success\n");
}

Sleep(1000);
hPipeRead = CreateFile(TEXT("\\\\.\\Pipe\\test_read"), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
//创建文件存储读取来自管道的数据
char buffer[4096] = {0};
DWORD dwRead = 0;
BOOL rSuccess = false;

while (TRUE) {
rSuccess = ReadFile(hPipeRead, buffer, 4096, &dwRead, NULL);
if (!rSuccess) {
break;
}

printf("Received: %s", buffer);
}
}

DisconnectNamedPipe(hPipeWrite);
CloseHandle(hPipeWrite);
DisconnectNamedPipe(hPipeRead);
CloseHandle(hPipeRead);
system("pause");
return 0;
}
子进程代码child.cpp
1
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 <windows.h>
#include <process.h>
#include <cstring>
#include <cstdio>

int main() {
if (WaitNamedPipe(TEXT("\\\\.\\Pipe\\test_write"), NMPWAIT_WAIT_FOREVER)) {//等待函数
HANDLE hPipeWrite;
printf("Connection successful\n");

HANDLE hPipeRead = CreateFile(TEXT("\\\\.\\Pipe\\test_write"), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
//创建读文件句柄管道
char buffer[4096] = {0};
DWORD dwRead = 0;
BOOL rSuccess = false;

while (TRUE) {
rSuccess = ReadFile(hPipeRead, buffer, 4096, &dwRead, NULL);
if (!rSuccess) {
break;
}
printf("%s\n", buffer);
if (buffer[0] == 's') {
printf("Received signal.\n");

hPipeWrite = CreateNamedPipe(TEXT("\\\\.\\Pipe\\test_read"), PIPE_ACCESS_DUPLEX, //创建写文件内容管道
PIPE_READMODE_BYTE | PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, 0, 0, NMPWAIT_WAIT_FOREVER, NULL);
if (ConnectNamedPipe(hPipeWrite, NULL)) {
FILE *fp = fopen("example.txt", "r");
char s[4096] = {0};
while (fgets(s, 100, fp) != NULL) {
DWORD dwBytesWritten;
WriteFile(hPipeWrite, s, 4096, &dwBytesWritten, NULL);
printf("Sent: %s", s);
}
fclose(fp);
break;
}


}
}

FlushFileBuffers(hPipeRead);
DisconnectNamedPipe(hPipeRead);
CloseHandle(hPipeRead);
DisconnectNamedPipe(hPipeWrite);
CloseHandle(hPipeWrite);
}
Sleep(10000);
return 0;
}

【实验截图】

image-20220603155307642

image-20220603155325352

【实验心得体会】

掌握命名匿名管道通信,通过指定路径创建命名管道