-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.c
More file actions
299 lines (243 loc) · 7.73 KB
/
main.c
File metadata and controls
299 lines (243 loc) · 7.73 KB
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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
#include <sys/wait.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <time.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/sem.h>
#include <string.h>
#include <sys/shm.h>
#include <sys/mman.h>
void* f_pipe_w(void* arg)
{
// printf("[[[ %s_w ]]]: pipe() first then fork(), so don't test\n", (char*)arg);
return NULL;
}
void* f_pipe_r(void* arg)
{
printf("[[[ %s_r ]]]: pipe() first then fork(), so don't test\n", (char*)arg);
return NULL;
}
void* f_fifo_w(void* arg)
{
int fd = 0;
time_t tp;
char buf[1024] = {0};
if(mkfifo("appfifo", 0666) < 0 && errno!=EEXIST) { // 创建FIFO管道
perror("fifo: can't open appfifo\n");
return NULL;
}
fd = open("appfifo", O_WRONLY); // 单独open 读端或写端会阻塞,直到另一进程打开写或读。可以使用 O_NONBLOCK 避免阻塞
for (int i=0; i<1; ++i) {
time(&tp);
int n = sprintf(buf, "fifo_w: timeis %s", ctime(&tp)); // ctime() 会加\n
write(fd, buf, n+1);
}
close(fd);
return NULL;
}
void* f_fifo_r(void* arg)
{
int fd = 0;
int len = 0;
char buf[1024] = {0};
if(mkfifo("appfifo", 0666) < 0 && errno!=EEXIST) { // 创建FIFO管道
perror("fifo_r: can't open appfifo\n");
return NULL;
}
fd = open("appfifo", O_RDONLY);
while((len = read(fd, buf, 1024)) > 0) // 读取FIFO管道
printf("[[[ fifo_r ]]]: %s", buf);
close(fd);
return NULL;
}
typedef struct {
long mtype; // 第一成员必须是类型
int a[3]; // 后面的成员无所谓
char c;
} msq_st;
void* f_msgqueue_w(void* arg)
{
char* const msqfile = "/etc/passwd";
key_t key;
int proj_id = 'z';
int msqid;
msq_st msg = {0};
key = ftok(msqfile, proj_id);
msqid = msgget(key, IPC_CREAT|0777);
msg.mtype = 888; // 设置一个 类型
msg.a[0] = 111;
msg.a[2] = 333;
msg.c = 'X';
msgsnd(msqid, &msg, sizeof(msg.a) + sizeof(msg.c), 0);
return NULL;
}
void* f_msgqueue_r(void* arg) // 这里关
{
char* const msqfile = "/etc/passwd";
key_t key;
int proj_id = 'z';
int msqid;
msq_st msg = {0};
key = ftok(msqfile, proj_id);
msqid = msgget(key, IPC_CREAT|0777);
msgrcv(msqid, &msg, sizeof(msg.a) + sizeof(msg.c), 888, 0);
printf("[[[ msgqueue_r ]]]: mtype=%ld, a={%d,%d,%d}, c=%c\n", msg.mtype,
msg.a[0],
msg.a[1],
msg.a[2],
msg.c);
return NULL;
}
void* f_semaphore_w(void* arg)
{
char* const semfile = "/etc/passwd";
key_t key;
int proj_id = 'z';
int semid;
sleep(1); // 等待 f_semaphore_r 初始化, 如果没有初始化 semid集 就V操作,之后P操作是没有资源的
key = ftok(semfile, 'z');
semid = semget(key, 1, IPC_CREAT|0666);
// v操作 释放资源
struct sembuf sbuf = {0};
sbuf.sem_num = 0;
sbuf.sem_op = 1;
sbuf.sem_flg = SEM_UNDO;
semop(semid, &sbuf, 1);
printf("[[[ semaphore_w ]]]: oprate V\n");
return NULL;
}
void* f_semaphore_r(void* arg)
{
char* const semfile = "/etc/passwd";
key_t key;
int proj_id = 'z';
int semid;
key = ftok(semfile, 'z');
semid = semget(key, 1, IPC_CREAT|0666);
// init
semctl(semid, 0, SETVAL, 0);
// semctl(semid, 0, SETVAL, 1); 信号量集semid 中序号0信号量 初始化成 1, 可以做互斥信号量使用
printf("[[[ semaphore_r ]]]: init\n");
// p操作 等待资源
struct sembuf sbuf = {0};
sbuf.sem_num = 0; // 信号量序号
sbuf.sem_op = -1; // p操作
sbuf.sem_flg = SEM_UNDO; // 当信号量操作导致进程被阻塞(比如等待信号量为0时),然后进程被信号中断,
// 导致操作未完成,此时如果设置了SEM_UNDO标志,
// 系统会自动撤销之前对信号量的操作,使得信号量的值回到原来的状态
// 简而言之,SEM_UNDO标志用于确保信号量操作的原子性,以避免因为进程意外终止而导致的资源泄漏或者状态异常
semop(semid, &sbuf, 1); // 操作个数是1,sbf可以是一个数组
printf("[[[ semaphore_r ]]]: oprate P\n");
// del_sem
semctl(semid, 0, IPC_RMID);
return NULL;
}
void* f_shmem_w(void* arg)
{
char* const shmfile = "/etc/passwd";
key_t key;
int proj_id = 'y';
int shmid;
char* shm = NULL;
int SHMSIZE = 1024;
key = ftok(shmfile, proj_id);
shmid = shmget(key, SHMSIZE, IPC_CREAT|0666);
shm = shmat(shmid, 0, 0);
sprintf(shm, "aa-bb-cc-dd");
shmdt(shm);
return NULL;
}
void* f_shmem_r(void* arg)
{
char* const shmfile = "/etc/passwd";
key_t key;
int proj_id = 'y';
int shmid;
char* shm = NULL;
int SHMSIZE = 1024;
key = ftok(shmfile, proj_id);
sleep(1); // 等待 f_shmem_w 给 shm 写字符串
shmid = shmget(key, SHMSIZE, IPC_CREAT|0666); // IPC_EXCL|IPC_CREAT|0666 如果存在报错
shm = shmat(shmid, 0, 0);
printf("[[[ shmem_r ]]]: %s\n", shm);
shmdt(shm);
shmctl(shmid, IPC_RMID, NULL);
return NULL;
}
void* f_mmap_w(void* arg)
{
size_t len = 20;
int fd = open("mmap.file", O_RDWR|O_CREAT|O_TRUNC, 0644); // O_RDWR不存在则创建 O_TRUNC截断成0长度
ftruncate(fd, 20); // 拓展文件大小为 20
char* p = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
strcpy(p, "AA-BB-CC-DD");
munmap(p, len);
return NULL;
}
void* f_mmap_r(void* arg)
{
size_t len = 20;
int fd = open("mmap.file", O_RDWR|O_CREAT, 0644);
sleep(1);
char* p = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
printf("[[[ mmap_r ]]]: %s\n", p);
munmap(p, len);
return NULL;
}
typedef struct {
void* desc;
void*(*f_w)(void*);
void*(*f_r)(void*);
} pcontext;
pcontext pcont[] = {
{"pipe", f_pipe_w, f_pipe_r},
{"fifo", f_fifo_w, f_fifo_r},
{"msg queue", f_msgqueue_w, f_msgqueue_r}, // 传递数据
{"semaphore", f_semaphore_w, f_semaphore_r}, // 一般仅计数
{"shmem", f_shmem_w, f_shmem_r}, // 在一块公共内存区建立映射,超高速通信
{"mmap", f_mmap_w, f_mmap_r}, // 在每个进程中都会开辟一段映射空间,比shmem略低效但是可持续化
};
int main(int argc, char** argv)
{
int rt = 0;
int i = 0, pid = 0, ppid = 0;
pthread_t ctid[255] = {0}, ptid[255];
ppid = getpid();
printf("--- partent pid:%d\n", ppid);
fflush(stdout);
for (i = 0; i < sizeof(pcont)/sizeof(pcont[0]); ++i) {
if ((pid = fork()) == 0) {
printf("--- child pid:%d\n", getpid());
/* IPC 写 */
rt = pthread_create(&ctid[i], NULL, pcont[i].f_w, pcont[i].desc);
break;
}
}
if (!pid) {
rt = pthread_join(ctid[i], NULL); // 在子进程中等待子线程
}
/* IPC 读 */
if (pid) {
for ( i = 0; i < sizeof(pcont)/sizeof(pcont[0]); ++i) {
rt = pthread_create(&ptid[i], NULL, pcont[i].f_r, pcont[i].desc);
}
}
if (pid) { // 父进程 等待所有子进程退出再退出
int status;
for ( i = 0; i < sizeof(pcont)/sizeof(pcont[0]); ++i) {
wait(&status);
rt = pthread_join(ptid[i], NULL); // 这里父进程子线程比较多,就按顺序等得了
}
}
printf("%s pid:%d - rt:%d\n", (pid=getpid())==ppid?"--- partent":"--- child", pid, rt);
return rt;
}