UNIX操作系统中进程通信机制的应用
UNIX系统具有丰富的进程通信手段,其中包括信号、信号灯、管道、消息传递等,这些进程通信机制能有效地完成多个进程之间的信息共享和数据交换,从而保证进程间的协同工作,本文给出了利用信号和信号灯完成特定工作的两个实例。
一、信号灯互斥功能的应用
在多用户操作系统中,信号灯是防止两个或多个进程同时访问共享资源的一种机制。在铁路系统中信号灯可防止两列火车在同一轨道上相撞在计算机系统中,信号灯能保证访问共享资源不会发生混乱。互斥操作要求任何时刻只能有一个或一类进程访问信号灯(执行一个特定的代码区域)。
互斥的应用非常广泛,UNIX操作系统提供了多种用户对共享资源的访问方法;多用户数据库管理系统为保证数据的完整性提供了加锁和解锁功能。另外在设计管理信息系统时经常要进行汇总处理,此时需要加入完全互斥功能;在设计操作员注册管理程序时,有时要求同一时刻只允许每个操作岫次,这就要求具有部分互斥功能。
下面的TEST.C程序程序说明了利用信号灯实现互斥的方法,其中函数Initsem()根据互斥条件确定是否进入互斥临界区,在需进入完全互斥时,只需将KEY 为某个常量即可。
test c
# include
# include
main (argc,argv)
int argc;
char * argv []
{
int semid;
if ( (semid=initsem(operate-ID))
P (semid) ;
· /*临界区*/
·
·
V (semid) ;
·
·
·
initsem(op)
char * op;
{
int id,status=0,semid;
key-t Key ,ftok()
id=atoi(op);
key=ftok(getenv("HOME"),id);/*相同Key值互斥*/
if (semid=semget(key,1,SEMPERM‖IPC-CREAT‖IPC-EXCL))==-1)} if (errno==EEXIST)
semid=semget(key,1,0);
}
else/*if created...*/
status=semct1(semid,0,SETVAL,1);
if(semid==-1‖status==-1){
perror("initsem failed")
return(-1);
}else
return(semid);/*all okay*/
}
P (semid)
int semid;
{
struct sembufp-buf;
p-buf.sem-num=0;
p-buf.sem-op=-1;
p-buf.sem-flg=IPC-NOWAIT;
if (semop (semid, & p-buf,1)==-1) {
perror ("p (semid) falsed");
exit (1);
} else
return (0);
}
V (semid)
int semid;
{
struct sembufv-buf,
v-buf.sem-num=0;
v-buf.sem-op=1;
v-buf.sem-flg=IPC-NOWAIT;
if (semop (semid, &v-buf,1)==-1) {
perror (" v (semid) failed");
exit (1);
} else
return (0)
}
#include
#include
extern int errno;
#define SEMPERM 0600
#define TRUE1
#define FALSE 0
二、用信号实现打印进程的控制
在大多数应用程序中,都包含打印模块,以实现报表、文本等信息的打印, C程序员常用fprint (fp,"")来设计打印程序,打印流程不能中断。若打印信息很长时,用户常遇到意外情况,如打印机卡纸等,此时一般要重新打印报表,浪费时间和纸张,因此打印程序能随时中断和继续,使用户能随时处理一些打印中出现的问题是非常必要的。
C语言中的标准函数signal(sig,func)可实现软中断,其功能为:当接收到信呈sig时,程序转去执行函数func,func返回后,程序从中断处继续执行重复使用中断需重新调用signal函数,另外一对标准函数setjmp(pos)和longimp(pos,arg) 可是实现远程跳转,setjmp(pos)能把控制传回被保存的位置,其中变量arg 作为setjmp()的返回值。
根据以上所述,笔者编写了下列打印程序,使用户在打印过程中遇到异常情况需要处理时,可以按DEL键中断打印,程序转而执行PRSTOP函数,通过输入某种条件,决定从中断处继续打印或远程跳转以完成退出打印或重新打印等功能。
#include
#include
#include
jmp-buf pos; /*保存堆栈环境*/
main()
{
FILE * fp;
int i,n,c,prstop();
fp=fopen("/dev/lp0","w");
c=setjmp(pos); /*跳转位置*/
if(c==1)exit(0);
signal(SIGINT,prstop);
printf("按DEL键可暂停打印\n");/*DOS下用CTRL-C键*/
i=0;
n=30;
while(i++
/*打印报表*/
fprintf(fp,"LINE %d TEST TEST TEST TEST \n",i);
}
fclose(fp);
exit(0);
}
prstop()
{
char c;
printf("打印被中断,请选择:\n");
read(0,&c,1);
if(c!='0')longjmp(pos,c-'0'); /*跳转*/
/*PRSTOP返回从中断处继续打印*/
}
延伸阅读
文章来源于领测软件测试网 https://www.ltesting.net/