-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathproc.c
144 lines (117 loc) · 2.54 KB
/
proc.c
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
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/ipc.h>
#include <sys/shm.h>
int SEGMENT_ID;
int *SHARED_VAR;
void init_mem(void)
{
/*
* allocate shared memory segment
*
* key => shared memory segment of size equal to at least the value of size bytes
* size => sizeof(int)
* shmflag => 600 = owner read+write
*/
SEGMENT_ID = shmget(IPC_PRIVATE, sizeof(int), 0600);
if (SEGMENT_ID == -1) {
perror("Shared memory segment could not be created!\n");
exit(1);
}
/*
* shared memory attach
*
* shmaddr => attaching address, if NULL system chooses unused address
*/
SHARED_VAR = (int *)shmat(SEGMENT_ID, NULL, 0);
}
void clear_mem(void)
{
/* shared memory detach */
(void)shmdt(SHARED_VAR);
/*
* shared memory control
*
* int cmd => mark the segment to be destroyed
* struct shmid_ds *buf => NULL
*/
(void)shmctl(SEGMENT_ID, IPC_RMID, NULL);
}
void handle_interrupt(int sig)
{
/* on sigterm clear shared memory before exit */
printf("%d signal received\n", sig);
clear_mem();
exit(0);
}
void do_work(int n)
{
/* do some long work with variable in shared memory */
for (int i = 0; i < n; i++) {
/* start of critical section */
(*SHARED_VAR)++;
/* end of critical section */
if ((i & 1) == 0) {
sleep(rand() % 2);
}
}
}
int main(int argc, char *argv[])
{
/*
* this program forks N processes,
* each increases shared int value M times
*
* ./a.out N M
*/
int forks;
int fork_jobs;
pid_t child_pid;
int child_exst;
if (argc != 3) {
perror("Wrong number of arguments\n");
printf("Usage: %s <N> <M>\n", argv[0]);
exit(-1);
}
/* load N and M values from arguments */
forks = atoi(argv[1]);
fork_jobs = atoi(argv[2]);
/* set signal handler and shared memory */
srand(getpid());
init_mem();
signal(SIGINT, handle_interrupt);
/* set value to be calculated */
*SHARED_VAR = 0;
/* fork */
for (int i = 0; i < forks; i++) {
child_pid = fork();
if (child_pid < 0) {
/* fork error */
perror("Fork failed\n");
} else if (child_pid == 0) {
/* this is child */
do_work(fork_jobs);
exit(0);
} else {
/* this is parent */
printf("Parent pid=%d\tChild pid=%d\n", getpid(), child_pid);
}
}
for (int i = 0; i < forks; i++) {
wait(&child_exst);
/* use WEXITSTATUS to extract child process exit status */
}
/*
* End
*
* clear memory before exit
* otherwise, it stays in kernel even after program exits
*/
printf("Total=%d\n", *SHARED_VAR);
clear_mem();
return 0;
}