การสื่อสารระหว่างกระบวนการ - Semaphores
คำถามแรกที่อยู่ในใจคือทำไมเราต้องมีเซมาโฟร์? คำตอบง่ายๆเพื่อปกป้องภูมิภาคสำคัญ / ร่วมกันระหว่างกระบวนการต่างๆ
สมมติว่ากระบวนการต่างๆกำลังใช้รหัสภูมิภาคเดียวกันและหากทุกคนต้องการเข้าถึงแบบขนานผลลัพธ์จะซ้อนทับกัน ตัวอย่างเช่นผู้ใช้หลายคนกำลังใช้เครื่องพิมพ์เพียงเครื่องเดียว (ส่วนทั่วไป / ส่วนสำคัญ) เช่นผู้ใช้ 3 คนรับงาน 3 งานในเวลาเดียวกันหากงานทั้งหมดเริ่มต้นพร้อมกันเอาต์พุตของผู้ใช้หนึ่งรายการจะซ้อนทับกับอีกเครื่องหนึ่ง ดังนั้นเราจำเป็นต้องป้องกันโดยใช้เซมาโฟเรสนั่นคือล็อกส่วนวิกฤตเมื่อกระบวนการหนึ่งกำลังทำงานและปลดล็อกเมื่อเสร็จสิ้น สิ่งนี้จะเกิดขึ้นซ้ำสำหรับผู้ใช้ / กระบวนการแต่ละคนเพื่อไม่ให้งานหนึ่งทับซ้อนกับงานอื่น
โดยทั่วไป semaphores แบ่งออกเป็นสองประเภท -
Binary Semaphores - มีเพียงสองสถานะ 0 & 1 เท่านั้น ได้แก่ ล็อก / ปลดล็อกหรือพร้อมใช้งาน / ไม่พร้อมใช้งานการใช้งาน Mutex
Counting Semaphores - Semaphores ที่อนุญาตให้มีการนับทรัพยากรโดยพลการเรียกว่าการนับ semaphores
สมมติว่าเรามีเครื่องพิมพ์ 5 เครื่อง (ให้เข้าใจสมมติว่าเครื่องพิมพ์ 1 เครื่องรับงานได้ 1 งานเท่านั้น) และมีงานให้พิมพ์ 3 งาน ตอนนี้จะได้รับ 3 งานสำหรับเครื่องพิมพ์ 3 เครื่อง (งานละ 1 เครื่อง) อีก 4 งานเข้ามาในขณะที่กำลังดำเนินการ ตอนนี้มีเครื่องพิมพ์จาก 2 เครื่องมีกำหนดงาน 2 งานและเราเหลืองานอีก 2 งานซึ่งจะเสร็จสมบูรณ์หลังจากที่มีทรัพยากร / เครื่องพิมพ์เครื่องใดเครื่องหนึ่งเท่านั้น การจัดกำหนดการแบบนี้ตามความพร้อมของทรัพยากรสามารถดูได้ว่าเป็นการนับเซมาโฟร์
ในการซิงโครไนซ์โดยใช้เซมาโฟร์ให้ทำตามขั้นตอนต่อไปนี้ -
Step 1 - สร้างสัญญาณหรือเชื่อมต่อกับสัญญาณที่มีอยู่แล้ว (semget ())
Step 2 - ดำเนินการกับสัญญาณเช่นจัดสรรหรือปล่อยหรือรอทรัพยากร (semop ())
Step 3 - ดำเนินการควบคุมบนคิวข้อความ (semctl ())
ตอนนี้ให้เราตรวจสอบสิ่งนี้กับระบบที่เรามี
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
int semget(key_t key, int nsems, int semflg)
การเรียกระบบนี้สร้างหรือจัดสรรชุดเซมาฟอร์ System V จำเป็นต้องส่งผ่านอาร์กิวเมนต์ต่อไปนี้ -
อาร์กิวเมนต์แรกคีย์จดจำคิวข้อความ คีย์อาจเป็นได้ทั้งค่าตามอำเภอใจหรือค่าที่ได้มาจากฟังก์ชันไลบรารี ftok ()
อาร์กิวเมนต์ที่สอง nsems ระบุจำนวนของ semaphores ถ้าไบนารีเป็น 1 แสดงว่าต้องการชุดเซมาฟอร์ 1 ชุดหรือตามจำนวนชุดเซมาฟอร์ที่ต้องการ
อาร์กิวเมนต์ที่สาม semflg ระบุแฟล็ก / s เซมาฟอร์ที่ต้องการเช่น IPC_CREAT (การสร้างเซมาฟอร์หากไม่มีอยู่) หรือ IPC_EXCL (ใช้กับ IPC_CREAT เพื่อสร้างเซมาฟอร์และการเรียกล้มเหลวหากมีเซมาฟอร์อยู่แล้ว) จำเป็นต้องผ่านการอนุญาตเช่นกัน
Note - อ้างอิงส่วนก่อนหน้าสำหรับรายละเอียดเกี่ยวกับการอนุญาต
การเรียกนี้จะส่งคืนตัวระบุเซมาฟอร์ที่ถูกต้อง (ใช้สำหรับการเรียกเซมาโฟร์ต่อไป) เมื่อสำเร็จและ -1 ในกรณีที่ล้มเหลว หากต้องการทราบสาเหตุของความล้มเหลวให้ตรวจสอบด้วยฟังก์ชัน errno variable หรือ perror ()
ข้อผิดพลาดต่างๆที่เกี่ยวข้องกับการเรียกนี้ ได้แก่ EACCESS (การอนุญาตถูกปฏิเสธ) EEXIST (ไม่สามารถสร้างคิวได้แล้ว) ENOENT (ไม่มีคิว) ENOMEM (หน่วยความจำไม่เพียงพอที่จะสร้างคิว) ENOSPC (ขีด จำกัด ชุดสูงสุด เกิน) ฯลฯ
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
int semop(int semid, struct sembuf *semops, size_t nsemops)
การเรียกระบบนี้ดำเนินการบนชุดเซมาฟอร์ System V ได้แก่ จัดสรรทรัพยากรรอทรัพยากรหรือปลดปล่อยทรัพยากร ต้องส่งผ่านข้อโต้แย้งต่อไปนี้ -
อาร์กิวเมนต์แรก semid ระบุตัวระบุชุดเซมาฟอร์ที่สร้างโดย semget ()
อาร์กิวเมนต์ที่สอง semops เป็นตัวชี้ไปยังอาร์เรย์ของการดำเนินการที่จะดำเนินการบนชุดเซมาฟอร์ โครงสร้างมีดังนี้ -
struct sembuf {
unsigned short sem_num; /* Semaphore set num */
short sem_op; /* Semaphore operation */
short sem_flg; /* Operation flags, IPC_NOWAIT, SEM_UNDO */
};
องค์ประกอบ sem_op ในโครงสร้างด้านบนระบุการดำเนินการที่ต้องดำเนินการ -
ถ้า sem_op เป็น –ve ให้จัดสรรหรือรับทรัพยากร บล็อกกระบวนการเรียกจนกว่ากระบวนการอื่น ๆ จะได้รับการปลดปล่อยทรัพยากรเพียงพอเพื่อให้กระบวนการนี้สามารถจัดสรรได้
ถ้า sem_op เป็นศูนย์กระบวนการเรียกจะรอหรือพักจนกว่าค่าเซมาฟอร์จะถึง 0
ถ้า sem_op เป็น + ve ปล่อยทรัพยากร
ตัวอย่างเช่น -
โครงสร้าง sembuf sem_lock = {0, -1, SEM_UNDO};
โครงสร้าง sembuf sem_unlock = {0, 1, SEM_UNDO};
อาร์กิวเมนต์ที่สาม nsemops คือจำนวนการดำเนินการในอาร์เรย์นั้น
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
int semctl(int semid, int semnum, int cmd, …)
การเรียกระบบนี้ดำเนินการควบคุมเซมาฟอร์ System V จำเป็นต้องส่งผ่านอาร์กิวเมนต์ต่อไปนี้ -
อาร์กิวเมนต์แรก semid คือตัวระบุของเซมาฟอร์ id นี้คือตัวระบุเซมาฟอร์ซึ่งเป็นค่าส่งคืนของการเรียกระบบ semget ()
อาร์กิวเมนต์ที่สอง semnum คือจำนวนของสัญญาณ semaphores มีจำนวนตั้งแต่ 0
อาร์กิวเมนต์ที่สาม cmd เป็นคำสั่งเพื่อดำเนินการควบคุมที่จำเป็นบนเซมาฟอร์
อาร์กิวเมนต์ที่สี่ประเภทยูเนี่ยนเซมุนขึ้นอยู่กับ cmd ในบางกรณีอาร์กิวเมนต์ที่สี่จะใช้ไม่ได้
ให้เราตรวจสอบเซมุนสหภาพ -
union semun {
int val; /* val for SETVAL */
struct semid_ds *buf; /* Buffer for IPC_STAT and IPC_SET */
unsigned short *array; /* Buffer for GETALL and SETALL */
struct seminfo *__buf; /* Buffer for IPC_INFO and SEM_INFO*/
};
โครงสร้างข้อมูล semid_ds ซึ่งกำหนดใน sys / sem.h มีดังนี้ -
struct semid_ds {
struct ipc_perm sem_perm; /* Permissions */
time_t sem_otime; /* Last semop time */
time_t sem_ctime; /* Last change time */
unsigned long sem_nsems; /* Number of semaphores in the set */
};
Note - โปรดดูหน้าคู่มือสำหรับโครงสร้างข้อมูลอื่น ๆ
สหภาพเซมุนอาร์กิวเมนต์; ค่าที่ถูกต้องสำหรับ cmd คือ -
IPC_STAT- คัดลอกข้อมูลของค่าปัจจุบันของสมาชิกแต่ละคนของ struct semid_ds ไปยังโครงสร้างที่ส่งผ่านที่ชี้โดย arg.buf คำสั่งนี้ต้องการสิทธิ์ในการอ่านสำหรับเซมาฟอร์
IPC_SET - ตั้งค่า ID ผู้ใช้ ID กลุ่มของเจ้าของสิทธิ์ ฯลฯ ที่โครงสร้าง semid_ds ชี้ให้เห็น
IPC_RMID - ลบชุด semaphores
IPC_INFO - ส่งกลับข้อมูลเกี่ยวกับขีด จำกัด ของสัญญาณและพารามิเตอร์ในโครงสร้าง semid_ds ที่ชี้โดย arg .__ buf
SEM_INFO - ส่งกลับโครงสร้าง seminfo ที่มีข้อมูลเกี่ยวกับทรัพยากรระบบที่ใช้โดยเซมาฟอร์
การเรียกนี้จะคืนค่า (ค่าที่ไม่ใช่ค่าลบ) ขึ้นอยู่กับคำสั่งที่ส่ง เมื่อประสบความสำเร็จ IPC_INFO และ SEM_INFO หรือ SEM_STAT จะส่งกลับดัชนีหรือตัวระบุของรายการที่ใช้สูงสุดตาม Semaphore หรือค่าของ semncnt สำหรับ GETPID หรือค่าของ sempid สำหรับ GETPID หรือค่าของ semval สำหรับ GETVAL 0 สำหรับการดำเนินการอื่น ๆ ที่ประสบความสำเร็จและ - 1 ในกรณีที่ล้มเหลว หากต้องการทราบสาเหตุของความล้มเหลวให้ตรวจสอบด้วยฟังก์ชัน errno variable หรือ perror ()
ก่อนที่จะดูโค้ดให้เราทำความเข้าใจกับการนำไปใช้งาน -
สร้างสองกระบวนการพูดว่าเด็กและผู้ปกครอง
สร้างหน่วยความจำแบบแบ่งใช้ส่วนใหญ่ที่จำเป็นในการจัดเก็บตัวนับและแฟล็กอื่น ๆ เพื่อระบุการสิ้นสุดกระบวนการอ่าน / เขียนลงในหน่วยความจำแบบแบ่งใช้
ตัวนับจะเพิ่มขึ้นโดยการนับโดยกระบวนการทั้งแม่และลูก การนับจะถูกส่งผ่านเป็นอาร์กิวเมนต์บรรทัดคำสั่งหรือใช้เป็นค่าเริ่มต้น (หากไม่ผ่านเป็นอาร์กิวเมนต์บรรทัดคำสั่งหรือค่าน้อยกว่า 10,000) เรียกว่ามีเวลานอนที่แน่นอนเพื่อให้แน่ใจว่าทั้งผู้ปกครองและเด็กเข้าถึงหน่วยความจำที่ใช้ร่วมกันในเวลาเดียวกันเช่นแบบขนาน
เนื่องจากตัวนับจะเพิ่มขึ้นในขั้นตอนที่ 1 โดยทั้งแม่และลูกค่าสุดท้ายควรเป็นสองเท่าของตัวนับ เนื่องจากกระบวนการทั้งแม่และลูกดำเนินการในเวลาเดียวกันตัวนับจะไม่เพิ่มขึ้นตามที่ต้องการ ดังนั้นเราจำเป็นต้องตรวจสอบให้แน่ใจว่ากระบวนการหนึ่งเสร็จสมบูรณ์ตามด้วยกระบวนการอื่น ๆ
การใช้งานทั้งหมดข้างต้นดำเนินการในไฟล์ shm_write_cntr.c
ตรวจสอบว่ามีการใช้ค่าตัวนับในไฟล์ shm_read_cntr.c หรือไม่
เพื่อให้แน่ใจว่าเสร็จสมบูรณ์โปรแกรม semaphore จะถูกนำไปใช้ในไฟล์ shm_write_cntr_with_sem.c ลบสัญญาณหลังจากเสร็จสิ้นกระบวนการทั้งหมด (หลังจากอ่านเสร็จจากโปรแกรมอื่น)
เนื่องจากเรามีไฟล์แยกต่างหากเพื่ออ่านค่าของตัวนับในหน่วยความจำที่ใช้ร่วมกันและไม่มีผลใด ๆ จากการเขียนโปรแกรมการอ่านยังคงเหมือนเดิม (shm_read_cntr.c)
การรันโปรแกรมเขียนในเทอร์มินัลเดียวและอ่านโปรแกรมจากเทอร์มินัลอื่นจะดีกว่าเสมอ เนื่องจากโปรแกรมจะดำเนินการเสร็จสิ้นหลังจากกระบวนการเขียนและการอ่านเสร็จสมบูรณ์แล้วจึงสามารถเรียกใช้โปรแกรมได้หลังจากเรียกใช้โปรแกรมเขียนอย่างสมบูรณ์ โปรแกรมเขียนจะรอจนกว่าโปรแกรมอ่านจะทำงานและเสร็จสิ้นหลังจากเสร็จสิ้นเท่านั้น
โปรแกรมที่ไม่มี semaphores
/* Filename: shm_write_cntr.c */
#include<stdio.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<sys/types.h>
#include<string.h>
#include<errno.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#define SHM_KEY 0x12345
struct shmseg {
int cntr;
int write_complete;
int read_complete;
};
void shared_memory_cntr_increment(int pid, struct shmseg *shmp, int total_count);
int main(int argc, char *argv[]) {
int shmid;
struct shmseg *shmp;
char *bufptr;
int total_count;
int sleep_time;
pid_t pid;
if (argc != 2)
total_count = 10000;
else {
total_count = atoi(argv[1]);
if (total_count < 10000)
total_count = 10000;
}
printf("Total Count is %d\n", total_count);
shmid = shmget(SHM_KEY, sizeof(struct shmseg), 0644|IPC_CREAT);
if (shmid == -1) {
perror("Shared memory");
return 1;
}
// Attach to the segment to get a pointer to it.
shmp = shmat(shmid, NULL, 0);
if (shmp == (void *) -1) {
perror("Shared memory attach");
return 1;
}
shmp->cntr = 0;
pid = fork();
/* Parent Process - Writing Once */
if (pid > 0) {
shared_memory_cntr_increment(pid, shmp, total_count);
} else if (pid == 0) {
shared_memory_cntr_increment(pid, shmp, total_count);
return 0;
} else {
perror("Fork Failure\n");
return 1;
}
while (shmp->read_complete != 1)
sleep(1);
if (shmdt(shmp) == -1) {
perror("shmdt");
return 1;
}
if (shmctl(shmid, IPC_RMID, 0) == -1) {
perror("shmctl");
return 1;
}
printf("Writing Process: Complete\n");
return 0;
}
/* Increment the counter of shared memory by total_count in steps of 1 */
void shared_memory_cntr_increment(int pid, struct shmseg *shmp, int total_count) {
int cntr;
int numtimes;
int sleep_time;
cntr = shmp->cntr;
shmp->write_complete = 0;
if (pid == 0)
printf("SHM_WRITE: CHILD: Now writing\n");
else if (pid > 0)
printf("SHM_WRITE: PARENT: Now writing\n");
//printf("SHM_CNTR is %d\n", shmp->cntr);
/* Increment the counter in shared memory by total_count in steps of 1 */
for (numtimes = 0; numtimes < total_count; numtimes++) {
cntr += 1;
shmp->cntr = cntr;
/* Sleeping for a second for every thousand */
sleep_time = cntr % 1000;
if (sleep_time == 0)
sleep(1);
}
shmp->write_complete = 1;
if (pid == 0)
printf("SHM_WRITE: CHILD: Writing Done\n");
else if (pid > 0)
printf("SHM_WRITE: PARENT: Writing Done\n");
return;
}
ขั้นตอนการรวบรวมและดำเนินการ
Total Count is 10000
SHM_WRITE: PARENT: Now writing
SHM_WRITE: CHILD: Now writing
SHM_WRITE: PARENT: Writing Done
SHM_WRITE: CHILD: Writing Done
Writing Process: Complete
ตอนนี้ให้เราตรวจสอบโปรแกรมการอ่านหน่วยความจำที่ใช้ร่วมกัน
/* Filename: shm_read_cntr.c */
#include<stdio.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<sys/types.h>
#include<string.h>
#include<errno.h>
#include<stdlib.h>
#include<unistd.h>
#define SHM_KEY 0x12345
struct shmseg {
int cntr;
int write_complete;
int read_complete;
};
int main(int argc, char *argv[]) {
int shmid, numtimes;
struct shmseg *shmp;
int total_count;
int cntr;
int sleep_time;
if (argc != 2)
total_count = 10000;
else {
total_count = atoi(argv[1]);
if (total_count < 10000)
total_count = 10000;
}
shmid = shmget(SHM_KEY, sizeof(struct shmseg), 0644|IPC_CREAT);
if (shmid == -1) {
perror("Shared memory");
return 1;
}
// Attach to the segment to get a pointer to it.
shmp = shmat(shmid, NULL, 0);
if (shmp == (void *) -1) {
perror("Shared memory attach");
return 1;
}
/* Read the shared memory cntr and print it on standard output */
while (shmp->write_complete != 1) {
if (shmp->cntr == -1) {
perror("read");
return 1;
}
sleep(3);
}
printf("Reading Process: Shared Memory: Counter is %d\n", shmp->cntr);
printf("Reading Process: Reading Done, Detaching Shared Memory\n");
shmp->read_complete = 1;
if (shmdt(shmp) == -1) {
perror("shmdt");
return 1;
}
printf("Reading Process: Complete\n");
return 0;
}
ขั้นตอนการรวบรวมและดำเนินการ
Reading Process: Shared Memory: Counter is 11000
Reading Process: Reading Done, Detaching Shared Memory
Reading Process: Complete
หากคุณสังเกตผลลัพธ์ข้างต้นตัวนับควรเป็น 20000 อย่างไรก็ตามเนื่องจากก่อนที่จะเสร็จสิ้นงานกระบวนการหนึ่งกระบวนการอื่น ๆ ก็กำลังประมวลผลแบบขนานเช่นกันค่าตัวนับจึงไม่เป็นไปตามที่คาดไว้ ผลลัพธ์จะแตกต่างกันไปในแต่ละระบบและจะแตกต่างกันไปตามแต่ละการดำเนินการ เพื่อให้แน่ใจว่ากระบวนการทั้งสองทำงานได้หลังจากเสร็จสิ้นภารกิจหนึ่งควรดำเนินการโดยใช้กลไกการซิงโครไนซ์
ตอนนี้ให้เราตรวจสอบแอปพลิเคชันเดียวกันโดยใช้ semaphores
Note - โปรแกรมการอ่านยังคงเหมือนเดิม
/* Filename: shm_write_cntr_with_sem.c */
#include<stdio.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<sys/sem.h>
#include<string.h>
#include<errno.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#define SHM_KEY 0x12345
#define SEM_KEY 0x54321
#define MAX_TRIES 20
struct shmseg {
int cntr;
int write_complete;
int read_complete;
};
void shared_memory_cntr_increment(int, struct shmseg*, int);
void remove_semaphore();
int main(int argc, char *argv[]) {
int shmid;
struct shmseg *shmp;
char *bufptr;
int total_count;
int sleep_time;
pid_t pid;
if (argc != 2)
total_count = 10000;
else {
total_count = atoi(argv[1]);
if (total_count < 10000)
total_count = 10000;
}
printf("Total Count is %d\n", total_count);
shmid = shmget(SHM_KEY, sizeof(struct shmseg), 0644|IPC_CREAT);
if (shmid == -1) {
perror("Shared memory");
return 1;
}
// Attach to the segment to get a pointer to it.
shmp = shmat(shmid, NULL, 0);
if (shmp == (void *) -1) {
perror("Shared memory attach: ");
return 1;
}
shmp->cntr = 0;
pid = fork();
/* Parent Process - Writing Once */
if (pid > 0) {
shared_memory_cntr_increment(pid, shmp, total_count);
} else if (pid == 0) {
shared_memory_cntr_increment(pid, shmp, total_count);
return 0;
} else {
perror("Fork Failure\n");
return 1;
}
while (shmp->read_complete != 1)
sleep(1);
if (shmdt(shmp) == -1) {
perror("shmdt");
return 1;
}
if (shmctl(shmid, IPC_RMID, 0) == -1) {
perror("shmctl");
return 1;
}
printf("Writing Process: Complete\n");
remove_semaphore();
return 0;
}
/* Increment the counter of shared memory by total_count in steps of 1 */
void shared_memory_cntr_increment(int pid, struct shmseg *shmp, int total_count) {
int cntr;
int numtimes;
int sleep_time;
int semid;
struct sembuf sem_buf;
struct semid_ds buf;
int tries;
int retval;
semid = semget(SEM_KEY, 1, IPC_CREAT | IPC_EXCL | 0666);
//printf("errno is %d and semid is %d\n", errno, semid);
/* Got the semaphore */
if (semid >= 0) {
printf("First Process\n");
sem_buf.sem_op = 1;
sem_buf.sem_flg = 0;
sem_buf.sem_num = 0;
retval = semop(semid, &sem_buf, 1);
if (retval == -1) {
perror("Semaphore Operation: ");
return;
}
} else if (errno == EEXIST) { // Already other process got it
int ready = 0;
printf("Second Process\n");
semid = semget(SEM_KEY, 1, 0);
if (semid < 0) {
perror("Semaphore GET: ");
return;
}
/* Waiting for the resource */
sem_buf.sem_num = 0;
sem_buf.sem_op = 0;
sem_buf.sem_flg = SEM_UNDO;
retval = semop(semid, &sem_buf, 1);
if (retval == -1) {
perror("Semaphore Locked: ");
return;
}
}
sem_buf.sem_num = 0;
sem_buf.sem_op = -1; /* Allocating the resources */
sem_buf.sem_flg = SEM_UNDO;
retval = semop(semid, &sem_buf, 1);
if (retval == -1) {
perror("Semaphore Locked: ");
return;
}
cntr = shmp->cntr;
shmp->write_complete = 0;
if (pid == 0)
printf("SHM_WRITE: CHILD: Now writing\n");
else if (pid > 0)
printf("SHM_WRITE: PARENT: Now writing\n");
//printf("SHM_CNTR is %d\n", shmp->cntr);
/* Increment the counter in shared memory by total_count in steps of 1 */
for (numtimes = 0; numtimes < total_count; numtimes++) {
cntr += 1;
shmp->cntr = cntr;
/* Sleeping for a second for every thousand */
sleep_time = cntr % 1000;
if (sleep_time == 0)
sleep(1);
}
shmp->write_complete = 1;
sem_buf.sem_op = 1; /* Releasing the resource */
retval = semop(semid, &sem_buf, 1);
if (retval == -1) {
perror("Semaphore Locked\n");
return;
}
if (pid == 0)
printf("SHM_WRITE: CHILD: Writing Done\n");
else if (pid > 0)
printf("SHM_WRITE: PARENT: Writing Done\n");
return;
}
void remove_semaphore() {
int semid;
int retval;
semid = semget(SEM_KEY, 1, 0);
if (semid < 0) {
perror("Remove Semaphore: Semaphore GET: ");
return;
}
retval = semctl(semid, 0, IPC_RMID);
if (retval == -1) {
perror("Remove Semaphore: Semaphore CTL: ");
return;
}
return;
}
ขั้นตอนการรวบรวมและดำเนินการ
Total Count is 10000
First Process
SHM_WRITE: PARENT: Now writing
Second Process
SHM_WRITE: PARENT: Writing Done
SHM_WRITE: CHILD: Now writing
SHM_WRITE: CHILD: Writing Done
Writing Process: Complete
ตอนนี้เราจะตรวจสอบค่าตัวนับตามขั้นตอนการอ่าน
ขั้นตอนการดำเนินการ
Reading Process: Shared Memory: Counter is 20000
Reading Process: Reading Done, Detaching Shared Memory
Reading Process: Complete