-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathwrite.c
More file actions
145 lines (117 loc) · 4.39 KB
/
write.c
File metadata and controls
145 lines (117 loc) · 4.39 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
#include "head.h"
int main(int argc, char *argv[])
{
/**
* Takes the arguments in the command line and integer 'ringBufferSize'
* gets assigned a size for the memory.
*
* put ':' at the starting of the string so compiler can distinguish between '?' and ':' .
*/
while ((option = getopt(argc, argv, ":m:")) != -1) { //get option from the getopt() method
switch (option){
case 'm':
ringBufferSize = strtol(optarg, &p, 10);
if(ringBufferSize <= 0){
fprintf(stderr,"Ring buffer size must be > 0!\n");
break;
}
break;
case ':':
fprintf(stderr,"Option needs a value!\n");
break;
case '?':
fprintf(stderr,"Unknown option: %c!\n", optopt);
break;
}
}
/**
* Request a key.
* The key is linked to a filename,
* so that other programs can access it.
*/
key = ftok(FILENAME, 0);
if (key == IPC_REST_ERROR) {
return IPC_REST_ERROR;
}
/**
* Get shared memory block - Create it, if it doesn't exist
* and returns a valid shared memory identifier. On error, -1
*/
int shared_block_id = shmget(key, ringBufferSize, 0644 | IPC_CREAT);
if (shared_block_id == IPC_REST_ERROR) {
return IPC_REST_ERROR;
}
/**
* Map the shared block into the address space of the calling process
* and give me a pointer to it.
*/
addressSpace = shmat(shared_block_id, NULL, 0);
if (addressSpace == (char *)IPC_REST_ERROR) {
return IPC_REST_ERROR;
}
/* A new semaphore is created or an existing one is opened, Init value set to 0. */
sem_t *sem_read = sem_open(SEMAPHORE_ZERO, O_CREAT, S_IRWXU | S_IRWXG, 0);
if (sem_read == SEM_FAILED) {
fprintf(stderr, "ERROR with sem_open SEMAPHORE_ZERO: %s\n", strerror(errno));
return IPC_REST_ERROR;
}
/* A new semaphore is created or an existing one is opened, Init value set to ringBufferSize. */
sem_t *sem_write = sem_open(SEMAPHORE_OCCUPIED, O_CREAT, ringBufferSize);
if (sem_write == SEM_FAILED) {
fprintf(stderr, "ERROR with sem_open SEMAPHORE_OCCUPIED: %s\n", strerror(errno));
return IPC_REST_ERROR;
}
/* We store here the first and last address of our created memory area to create the ring buffer. */
addressSpaceHead = addressSpace;
addressSpaceTail = (addressSpace + ringBufferSize - 1);
/**
* Here is a while(1) created because we cannot
* know in advance when the input of the STDIN (EOF) is reached.
*/
while (1){
/**
* Check that 'sem_read' is blocked since it is 0 and cannot be decremented further
* until sem_post(sem_read) is released in read.c program .
*/
while (sem_wait(sem_read) == -1){
if(errno != EINTR){ //TODO: EINTR NECASSARY??
fprintf(stderr,"Error with sem_read: %s\n",strerror(errno));
return -1;
}
}
/* If EOF is reached unlock/upcount sem_read and leave the endless loop */
if(*addressSpace == EOF){
if(sem_post(sem_write) == -1){
fprintf(stderr,"Error with sem_write: %s",strerror(errno));
return -1;
}
/* with break we get out of the endless while. */
break;
}
/**
* We check errors while printing the read characters to STDOUT
* and 'clearerr' is needed to detect this. The function clearerr() clears
* the end-of-file and error indicators for the stream pointed to by STREAM.
*/
clearerr(stdout);
if(fputc(*addressSpace, stdout) == EOF){
if(ferror(stdout) != 0){ //return the error indicator for the STREAM
fprintf(stderr,"Error with writing in STDOUT: %s",strerror(errno));
return -1;
}
}
/* Our created shared memory ring buffer */
if (addressSpace != addressSpaceTail){
addressSpace += 1;
}
else{
addressSpace = addressSpaceHead;
}
//Unlock/upcount semaphor
if(sem_post(sem_write) == -1){
fprintf(stderr,"Error with sem_write: %s",strerror(errno));
return -1;
}
}
return 0;
}