Linux进程通信 作业

有名管道

  1. 父进程创建一个有名管道,然后创建 1 个子进程,父进程阻塞的方式等待有名管道的信息,当读取到信息之后,在屏幕上打印出来;当从有名管道中读取到“QUIT”之后,父进程终止。
  2. 子进程 1 使用定时器,每 5 秒钟向有名管道输入“this is process 1”;当收到信号 SIGQUIT 时,向有名管道输出“QUIT”,并在屏幕上输出“process 1 exit”之后,进程终止。

提交形式

  1. 代码
  2. 运行结果截图

Code

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
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <signal.h>

#define FIFO "/tmp/fifo"
#define MAX_BUFFER_SIZE PIPE_BUF

pid_t pid, pr;
char buff[MAX_BUFFER_SIZE];

void child_func(int sign_no) {
if (sign_no == SIGALRM) {
int fdChild = open(FIFO, O_WRONLY);
if (fdChild == -1) {
printf("Open fifo file error\n");
exit(1);
}
sscanf("this is progress 1\n", "%[^\n]", buff);
write(fdChild, buff, MAX_BUFFER_SIZE);
close(fdChild);
} else if (sign_no == SIGQUIT) {
int fdChild = open(FIFO, O_WRONLY);
if (fdChild == -1) {
printf("Open fifo file error\n");
exit(1);
}
sscanf("QUIT\n", "%[^\n]", buff);
write(fdChild, buff, MAX_BUFFER_SIZE);
close(fdChild);
printf("process 1 exit.\n");
exit(0);
}
}

int main() {
pid = fork();

if (pid < 0) {
printf("Fork error\n");
exit(1);
} else if (pid == 0) { // child thread
signal(SIGALRM, child_func); // handle SIG_ALARM
signal(SIGQUIT, child_func); // handle SIGQUIT
while (1) {
alarm(5); // ALARM SIGN
sleep(5);
}
} else { // parent thread
if (access(FIFO, F_OK) == -1) { // if unexist then create
if ((mkfifo(FIFO, 0666) < 0) && errno != EEXIST) {
printf("Cannot create fifo file\n");
exit(1);
}
}

int fdParent = open(FIFO, O_RDONLY);
if (fdParent == -1) {
printf("Open fifo file error\n");
exit(1);
}
do {
signal(SIGQUIT, child_func); // handle the SIGQUIT from parent thread
pr = waitpid(pid, NULL, WNOHANG);
memset(buff, 0, sizeof(buff)); // reset the buff

read(fdParent, buff, MAX_BUFFER_SIZE); // read buff
if (strcmp("", buff) == 0) continue;
if (strcmp("QUIT", buff) == 0) exit(0); // if buff equals "QUIT" then quit
printf("%s\n", buff);
sleep(1);
} while (pr == 0);
close(fdParent);
}
exit(0);
}

信号量机制

  1. 一个海底隧道中只有一个车道,规定同一个方向的可以连续过隧道;某方向有列车过隧道时,另一个方向的列车就要等待,现在东岸和西岸都有列车要过隧道,如果把每个过隧道的列车看作一个进程,为保证安全,使用信号量机制实现正确管理。
  2. 使用屏幕输出信息,来表示列车通行情况。

提交形式

  1. 代码
  2. 运行结果截图

Code

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
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

int main() {
pid_t A;
int sem_id;

sem_id = semget(ftok(".", 'a'), 1, 0666 | IPC_CREAT);
init_sem(sem_id, 1);

A = fork();
if (A == -1) {
perror("Fork error\n");
exit(1);
} else if (A == 0) {
while (1) {
sem_p(sem_id);
printf("A -> B\n");
sem_v(sem_id);
}
} else {
while (1) {
sem_p(sem_id);
printf("B -> A\n");
sem_v(sem_id);
}
}
del_sem(sem_id);
exit(0);
}
1
2
3
4
5
union semun {
int val;
struct semid_ds* buf;
unsigned short* array;
};
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
#include "sem_com.h"
#include <sys/sem.h>

int init_sem(int sem_id, int init_value) {
union semun sem_union;
sem_union.val = init_value;

if (semctl(sem_id, 0, SETVAL, sem_union) == -1) {
perror("Initialize semaphore");
return -1;
}

return 0;
}


int del_sem(int sem_id) {
union semun sem_union;

if (semctl(sem_id, 0, IPC_RMID, sem_union) == -1) {
perror("Delete semaphore");
return -1;
}

return 0;
}

int sem_p(int sem_id) {
struct sembuf sem_b;
sem_b.sem_num = 0;
sem_b.sem_op = -1;
sem_b.sem_flg = SEM_UNDO;
if (semop(sem_id, &sem_b, 1) == -1) {
perror("P operation");
return -1;
}

return 0;
}

int sem_v(int sem_id) {
struct sembuf sem_b;
sem_b.sem_num = 0;
sem_b.sem_op = 1;
sem_b.sem_flg = SEM_UNDO;
if (semop(sem_id, &sem_b, 1) == -1) {
perror("V operation");
return -1;
}

return 0;
}