实验四 Linux进程互斥

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

实验四 Linux进程互斥

一、实验目的

熟悉Linux下信号量机制,能够使用信号量实现在并发进程间的互斥和同步。

二、实验题目

使用共享存储区机制,使多个并发进程分别模拟生产者-消费者模式同步关系、临界资源的互斥访问关系,使用信号量机制实现相应的同步和互斥。

三、背景材料

(一)需要用到的系统调用

实验可能需要用到的主要系统调用和库函数在下面列出,详细的使用方法说明通过“man 2 系统调用名”或者“man 3 函数名”命令获取。

fork() 创建一个子进程,通过返回值区分是在父进程还是子进程中执行;

wait() 等待子进程执行完成;

shmget() 建立一个共享存储区;

shmctl() 操纵一个共享存储区;

s hmat() 把一个共享存储区附接到进程内存空间;

shmdt() 把一个已经附接的共享存储区从进程内存空间断开;

semget() 建立一个信号量集;

semctl() 操纵一个信号量集,包括赋初值;

semop() 对信号量集进行wait和signal操作;

signal() 设置对信号的处理方式或处理过程。

(二)模拟生产者-消费者的示例程序

本示例主要体现进程间的直接制约关系,由于使用共享存储区,也存在间接制约关系。进程分为服务进程和客户进程,服务进程只有一个,作为消费者,在每次客户进程改变共享存储区内容时显示其数值。各客户进程作为生产者,如果共享存储区内容已经显示(被消费),可以接收用户从键盘输入的整数,放在共享存储区。

编译后执行,第一个进程实例将作为服务进程,提示:

ACT CONSUMER!!! To end, try Ctrl+C or use kill.

服务进程一直循环执行,直到用户按Ctrl+C终止执行,或使用kill命令杀死服务进程。

其他进程实例作为客户进程,提示:

Act as producer. To end, input 0 when prompted.

客户进程一直循环执行,直到用户输入0。

示例程序代码如下:

#include

#include

#include

#include

#include

#include

#include

#include

#define MY_S HM KEY 10071500 // need to change

#define MY_S EM KEY 10071500 // need to change

void sigend(int);

int shmid, semid;

int main(void)

{

int *shmptr, semval, local;

struct sembuf semopbuf;

/*这个函数成功时返回共享内存的ID,失败时返回-1。*/

if((shmid=shmget(MY_SHMKEY, sizeof(int), IPC_CREA T|IPC_EXCL|0666)) < 0)

{ /* shared memory exists, act as client */

shmid=shmget(MY_SHMKEY, sizeof(int), 0666);

//建立一个信号量集函数执行成功,则返回信号量集的标识符(一个大于等于0的整数),失败,则返回–1

semid=semget(MY_SEMKEY, 2, 0666);

//返回共享内存的起始地址。失败时返回-1。允许本进程使用这块共享内存

shmptr=(int *)shmat(shmid, 0, 0);

printf("Act as producer. To end, input 0 when prompted.\n\n");

printf("Input a number:\n");

scanf("%d", &local);

while( local )

{

semopbuf.sem_num=0;

semopbuf.sem_op=-1;

semopbuf.sem_flg=SEM_UNDO;

semop(semid, &semopbuf, 1); /* P(S1)对信号量集进行wait和signal操作;*/

*shmptr = local;

semopbuf.sem_num=1;// 正数:释放相应的资源数,将sem_op的值加到信号量的值上

semopbuf.sem_op=1;//执行释放的资源

semopbuf.sem_flg=SEM_UNDO;

semop(semid, &semopbuf, 1); /* V(S2) */

printf("Input a number:\n");

scanf("%d", &local);

}

}

else /* acts as server */

{

//建立一个信号量集;

//参数nsems表示创建的信号量集中的信号量的个数,该参数只在创建信号量集时有效。

semid=semget(MY_SEMKEY, 2, IPC_CREA T|0666);

shmptr=(int *)shmat(shmid, 0, 0);

semval=1;

//操纵一个信号量集,包括赋初值;SETVAL设置信号量集中的一个单独的信号量的值 semctl(semid, 0, SETV AL, semval); /* set S1=1第二个参数是信号量数目*/

semval=0;

semctl(semid, 1, SETV AL, semval); /* set S2=0 */

//对信号的处理方式或处理过程

signal(SIGINT, sigend);由Interrupt Key产生,通常是CTRL+C或者DELETE。发送给所有ForeGround Group的进程按下CTRL+C产生SIGINT

signal(SIGTERM, sigend);请求中止进程,kill命令缺省发送

printf("ACT CONSUMER!!! To end, try Ctrl+C or use kill.\n\n");

while(1)

{

semopbuf.sem_num=1;

semopbuf.sem_op=-1;

semopbuf.sem_flg=SEM_UNDO;

semop(semid, &semopbuf, 1); /* P(S2) */

printf("Shared memory set to %d\n", *shmptr);

semopbuf.sem_num=0;

semopbuf.sem_op=1;

semopbuf.sem_flg=SEM_UNDO;

semop(semid, &semopbuf, 1); /* V(S1) */

}

}

}

void sigend(int sig)

{

shmctl(shmid, IPC_RMID, 0);

semctl(semid, IPC_RMID, 0);

exit(0);

}

(三)模拟临界资源访问的示例程序

本示例的临界资源是一个建立在共享存储区的栈,由服务进程建立并初始化。初始状态下共享栈满,里面顺序放置一系列正整数(自栈顶向下:1,2,3...),代表空闲块号。客户进程利用共享栈进行数据块的分配和释放,以得到、归还一个块号代表,并不进行任何后续操作。程序中getblock过程从共享栈中弹出一个块号(分配),relblock过程把一个已分配块号压入共享栈(释放)。为简单起见,已分配块号在本地也使用栈结构保存,因而每次释放的是最后分配的块号。

编译后执行,第一个进程实例将作为服务进程,提示:

NO OTHER OPERA TION but press Ctrl+C or use kill to end.

相关文档
最新文档