多进程双buffer读取并处理

题目要求

编写Linux平台下的两个C语言程序实现如下功能:
(1)X、Y两个进程相互配合实现对输入文件中数据的处理,并将处理结果写入输出文件。
(2)X进程负责读分块取输入文件,并将输入数据利用共享内存传输给Y进程。
(3)Y进程负责将读入的数据(假定皆为文本数据)全部处理成大写,然后写入输出文件。
(4)为提高并行效率,X、Y两个进程之间创建2个共享内存区A、B。X读入数据到A区,然后用Linux的信号或信号量机制通知Y进程进行处理;在Y处理A区数据时,X继续读入数据到B区;B区数据被填满之后,X进程通知Y进程处理,自己再继续向A区读入数据。如此循环直至全部数据处理完毕。

解题

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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <ctype.h>
#include <semaphore.h>
#include <sys/ipc.h>
#include <sys/shm.h>

const int BUFFER_SIZE = 2048;

int main(int argc, char const *argv[])
{
argv[1];
// 文件
int inputFile, outputFile;
inputFile = open(argv[1], O_RDONLY);
if(inputFile <= 0 ){
printf("no file %s \n", argv[1]);
return 0;
}
outputFile = open("./output.txt", O_WRONLY | O_CREAT, 0666);

// 信号量
sem_t *sem1;
sem_t *sem2;
sem1 = sem_open("sem1", O_CREAT, 0666, 1);
sem2 = sem_open("sem2", O_CREAT, 0666, 0);

// 共享内存
// 定义交换空间结构体
struct switchBuffer
{
char buffer[BUFFER_SIZE];
int flag;
};
struct switchBuffer *buffera; // 交换空间a,b
struct switchBuffer *bufferb;
int shmaId, shmbId;

// 创建共享内存
shmaId = shmget((key_t)11, sizeof(buffera), 0666 | IPC_CREAT);
shmbId = shmget((key_t)22, sizeof(bufferb), 0666 | IPC_CREAT);

// 主进程读取数据
// 子进程处理后写入数据
pid_t cpid;
cpid = fork();
if (cpid < 0)
{
printf("error in fork\n");
}
else if (cpid == 0)
{
// 子进程
printf("child process pid: %d \t", getpid());

// 共享内存映射到进程空间
buffera = (struct switchBuffer *)shmat(shmaId, 0, 0);
bufferb = (struct switchBuffer *)shmat(shmbId, 0, 0);
int switchFlag = 1;
while(1)
{
sem_wait(sem2);
if (switchFlag)
{
for (int i = 0; i < buffera->flag; ++i)
{
buffera->buffer[i] = toupper(buffera->buffer[i]);
}
write(outputFile, buffera->buffer, buffera->flag);
}
else
{
for (int i = 0; i < bufferb->flag; ++i)
{
bufferb->buffer[i] = toupper(bufferb->buffer[i]);
}
write(outputFile, bufferb->buffer, bufferb->flag);
}
switchFlag = !switchFlag;
sem_post(sem1);
}
}
else
{
// 主进程
// 共享内存映射到进程空间
buffera = (struct switchBuffer *)shmat(shmaId, 0, 0);
bufferb = (struct switchBuffer *)shmat(shmbId, 0, 0);

int fileFlag = 0;
int switchFlag = 1;

// 1.读取文件->buffer a
// 2.等待处理进程
// 3.触发处理进程
// 4.读取文件->buffer b
// 5.等待处理进程
// 6.触发处理进程

// 开始时预先触发2,开始运行任务
// 通过read文件为0判断终止条件
// 终止后再次等待处理线程处理最后的一个buffer
while (1)
{
if (switchFlag)
{
fileFlag = read(inputFile, buffera->buffer, BUFFER_SIZE);
buffera->flag = fileFlag;
}
else
{
fileFlag = read(inputFile, bufferb->buffer, BUFFER_SIZE);
bufferb->flag = fileFlag;
}
switchFlag = !switchFlag;
if (fileFlag <= 0)
break;
sem_wait(sem1);
sem_post(sem2);
}
sem_wait(sem1);
}

// destory
close(inputFile);
close(outputFile);
sem_close(sem1);
sem_close(sem2);
sem_unlink("sem1");
sem_unlink("sem2");
shmdt(buffera);
shmdt(bufferb);
shmctl(shmaId, IPC_RMID, 0);
shmctl(shmbId, IPC_RMID, 0);
printf("over\n");
return 0;
}
文章作者: ximikang
文章链接: http://ximikang.icu/2020/12/06/linux-homework/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Ximikang Blog