三个进程的信号量
Semaphores with three processes
一个内存位置被三个进程共享。每个进程独立地尝试将共享内存位置的内容从 1 增加到某个值,增量为 1。进程1的目标是100000,进程2的目标是200000,进程3的目标是300000。因此,当程序终止时,共享内存变量总共有600000(即这个值将由三个进程中的任何一个输出)最后完成)。我要使用信号量保护临界区。
我的问题是初始化信号量时每个进程的 SETVAL 都有问题。它一直打印 "Error detected in SETVAL",即使我将它设置为 1。正确的示例输出以及我的代码如下所示:
Sample output
From Process 1: counter = 100000.
From Process 2: counter = 300000.
From Process 3: counter = 600000.
Child with ID 2412 has just exited.
Child with ID 2411 has just exited.
Child with ID 2413 has just exited.
End of Simulation.
/*ass1*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/sem.h>
#define SEMKEY ((key_t) 400L)
// number of semaphores being created
#define NSEMS 2
/* change the key number */
#define SHMKEY ((key_t) 7890)
typedef struct
{
int value;
} shared_mem;
shared_mem *total;
//structure
int sem_id, sem_id2;
typedef union{
int val;
struct semid_ds *buf;
ushort *array;
} semunion;
static struct sembuf OP = {0,-1,0};
static struct sembuf OV = {0,1,0};
struct sembuf *P =&OP;
struct sembuf *V =&OV;
//function
int Pop()
{
int status;
status = semop(sem_id, P,1);
return status;
}
int Vop()
{
int status;
status = semop(sem_id, V,1);
return status;
}
/*----------------------------------------------------------------------*
* This function increases the value of shared variable "total"
* by one with target of 100000
*----------------------------------------------------------------------*/
void process1 ()
{
int k = 0;
while (k < 100000)
{
Pop();
if (total->value < 600000) {
total->value = total->value + 1;
}
Vop();
k++;
}
printf ("From process1 total = %d\n", total->value);
}
/*----------------------------------------------------------------------*
* This function increases the vlaue of shared memory variable "total"
* by one with a target 200000
*----------------------------------------------------------------------*/
void process2 ()
{
int k = 0;
while (k < 200000)
{
Pop();
if (total->value < 600000) {
total->value = total->value + 1;
}
Vop();
k++;
}
printf ("From process2 total = %d\n", total->value);
}
/*----------------------------------------------------------------------*
* This function increases the vlaue of shared memory variable "total"
* by one with a target 300000
*----------------------------------------------------------------------*/
void process3 ()
{
int k = 0;
while (k < 300000)
{
Pop();
if (total->value < 600000) {
total->value = total->value + 1;
}
Vop();
k++;
}
printf ("From process3 total = %d\n", total->value);
}
/*----------------------------------------------------------------------*
* MAIN()
*----------------------------------------------------------------------*/
int main()
{
int shmid;
int pid1;
int pid2;
int pid3;
int ID;
int status;
char *shmadd;
shmadd = (char *) 0;
//semaphores
int semnum = 0;
int value, value1;
semunion semctl_arg;
semctl_arg.val =1;
/* Create semaphores */
sem_id = semget(SEMKEY, NSEMS, IPC_CREAT | 0666);
if(sem_id < 0)
printf("creating semaphore");
sem_id2 = semget(SEMKEY, NSEMS, IPC_CREAT | 0666);
if(sem_id2 < 0)
printf("creating semaphore");
/* Initialize semaphore */
value1 =semctl(sem_id, semnum, SETVAL, semctl_arg);
value =semctl(sem_id, semnum, GETVAL, semctl_arg);
if (value < 1)
printf("Eror detected in SETVAL");
/* Create and connect to a shared memory segmentt*/
if ((shmid = shmget (SHMKEY, sizeof(int), IPC_CREAT | 0666)) < 0)
{
perror ("shmget");
exit (1);
}
if ((total = (shared_mem *) shmat (shmid, shmadd, 0)) == (shared_mem *) -1)
{
perror ("shmat");
exit (0);
}
total->value = 0;
if ((pid1 = fork()) == 0)
process1();
if ((pid1 != 0) && (pid2 = fork()) == 0)
process2();
if ((pid1 != 0 ) && (pid2 != 0) && (pid3 = fork()) == 0 )
process3();
waitpid(pid1, NULL, 0 );
waitpid(pid2, NULL, 0 );
waitpid(pid3, NULL, 0 );
if ((pid1 != 0) && (pid2 != 0) && (pid3 != 0))
{
waitpid(pid1);
printf("Child with ID %d has just exited.\n", pid1);
waitpid(pid2);
printf("Child with ID %d has just exited.\n", pid2);
waitpid(pid3);
printf("Child with ID %d has just exited.\n", pid3);
if ((shmctl (shmid, IPC_RMID, (struct shmid_ds *) 0)) == -1)
{
perror ("shmctl");
exit (-1);
}
printf ("\t\t End of Program\n");
/* De-allocate semaphore */
semctl_arg.val = 0;
status =semctl(sem_id, 0, IPC_RMID, semctl_arg);
if( status < 0)
printf("Error in removing the semaphore.\n");
}
}
一些基础知识 - IPC 比进程持续时间更长,因此如前所述,使用 ipcs
和 ipcrm
删除 运行 之间的 pre-existing 个 IPC。确保在执行后删除 ipc
waitpid(pid1, NULL, 0 );
waitpid(pid2, NULL, 0 );
waitpid(pid3, NULL, 0 );
此部分将 运行 用于 children - 他们可能不应该。
total->value = total->value + 1;
IPC 不安全,因此可能会出现不同的结果(proc1 可能会覆盖 proc2 的增量)。
一个内存位置被三个进程共享。每个进程独立地尝试将共享内存位置的内容从 1 增加到某个值,增量为 1。进程1的目标是100000,进程2的目标是200000,进程3的目标是300000。因此,当程序终止时,共享内存变量总共有600000(即这个值将由三个进程中的任何一个输出)最后完成)。我要使用信号量保护临界区。 我的问题是初始化信号量时每个进程的 SETVAL 都有问题。它一直打印 "Error detected in SETVAL",即使我将它设置为 1。正确的示例输出以及我的代码如下所示:
Sample output
From Process 1: counter = 100000.
From Process 2: counter = 300000.
From Process 3: counter = 600000.
Child with ID 2412 has just exited.
Child with ID 2411 has just exited.
Child with ID 2413 has just exited.
End of Simulation.
/*ass1*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/sem.h>
#define SEMKEY ((key_t) 400L)
// number of semaphores being created
#define NSEMS 2
/* change the key number */
#define SHMKEY ((key_t) 7890)
typedef struct
{
int value;
} shared_mem;
shared_mem *total;
//structure
int sem_id, sem_id2;
typedef union{
int val;
struct semid_ds *buf;
ushort *array;
} semunion;
static struct sembuf OP = {0,-1,0};
static struct sembuf OV = {0,1,0};
struct sembuf *P =&OP;
struct sembuf *V =&OV;
//function
int Pop()
{
int status;
status = semop(sem_id, P,1);
return status;
}
int Vop()
{
int status;
status = semop(sem_id, V,1);
return status;
}
/*----------------------------------------------------------------------*
* This function increases the value of shared variable "total"
* by one with target of 100000
*----------------------------------------------------------------------*/
void process1 ()
{
int k = 0;
while (k < 100000)
{
Pop();
if (total->value < 600000) {
total->value = total->value + 1;
}
Vop();
k++;
}
printf ("From process1 total = %d\n", total->value);
}
/*----------------------------------------------------------------------*
* This function increases the vlaue of shared memory variable "total"
* by one with a target 200000
*----------------------------------------------------------------------*/
void process2 ()
{
int k = 0;
while (k < 200000)
{
Pop();
if (total->value < 600000) {
total->value = total->value + 1;
}
Vop();
k++;
}
printf ("From process2 total = %d\n", total->value);
}
/*----------------------------------------------------------------------*
* This function increases the vlaue of shared memory variable "total"
* by one with a target 300000
*----------------------------------------------------------------------*/
void process3 ()
{
int k = 0;
while (k < 300000)
{
Pop();
if (total->value < 600000) {
total->value = total->value + 1;
}
Vop();
k++;
}
printf ("From process3 total = %d\n", total->value);
}
/*----------------------------------------------------------------------*
* MAIN()
*----------------------------------------------------------------------*/
int main()
{
int shmid;
int pid1;
int pid2;
int pid3;
int ID;
int status;
char *shmadd;
shmadd = (char *) 0;
//semaphores
int semnum = 0;
int value, value1;
semunion semctl_arg;
semctl_arg.val =1;
/* Create semaphores */
sem_id = semget(SEMKEY, NSEMS, IPC_CREAT | 0666);
if(sem_id < 0)
printf("creating semaphore");
sem_id2 = semget(SEMKEY, NSEMS, IPC_CREAT | 0666);
if(sem_id2 < 0)
printf("creating semaphore");
/* Initialize semaphore */
value1 =semctl(sem_id, semnum, SETVAL, semctl_arg);
value =semctl(sem_id, semnum, GETVAL, semctl_arg);
if (value < 1)
printf("Eror detected in SETVAL");
/* Create and connect to a shared memory segmentt*/
if ((shmid = shmget (SHMKEY, sizeof(int), IPC_CREAT | 0666)) < 0)
{
perror ("shmget");
exit (1);
}
if ((total = (shared_mem *) shmat (shmid, shmadd, 0)) == (shared_mem *) -1)
{
perror ("shmat");
exit (0);
}
total->value = 0;
if ((pid1 = fork()) == 0)
process1();
if ((pid1 != 0) && (pid2 = fork()) == 0)
process2();
if ((pid1 != 0 ) && (pid2 != 0) && (pid3 = fork()) == 0 )
process3();
waitpid(pid1, NULL, 0 );
waitpid(pid2, NULL, 0 );
waitpid(pid3, NULL, 0 );
if ((pid1 != 0) && (pid2 != 0) && (pid3 != 0))
{
waitpid(pid1);
printf("Child with ID %d has just exited.\n", pid1);
waitpid(pid2);
printf("Child with ID %d has just exited.\n", pid2);
waitpid(pid3);
printf("Child with ID %d has just exited.\n", pid3);
if ((shmctl (shmid, IPC_RMID, (struct shmid_ds *) 0)) == -1)
{
perror ("shmctl");
exit (-1);
}
printf ("\t\t End of Program\n");
/* De-allocate semaphore */
semctl_arg.val = 0;
status =semctl(sem_id, 0, IPC_RMID, semctl_arg);
if( status < 0)
printf("Error in removing the semaphore.\n");
}
}
一些基础知识 - IPC 比进程持续时间更长,因此如前所述,使用 ipcs
和 ipcrm
删除 运行 之间的 pre-existing 个 IPC。确保在执行后删除 ipc
waitpid(pid1, NULL, 0 );
waitpid(pid2, NULL, 0 );
waitpid(pid3, NULL, 0 );
此部分将 运行 用于 children - 他们可能不应该。
total->value = total->value + 1;
IPC 不安全,因此可能会出现不同的结果(proc1 可能会覆盖 proc2 的增量)。