醒继续执行。
数据区队列首部Key13212#include
int msgget(key_t key, int msgflg);
int msgsnd(int msqid, struct msgbuf* msgp, int msgsz, int msgflg);
int msgrcv(int msqid, struct msgbuf* msgp, int msgsz, long msgtyp, int msgflg);
int msgctl(int msqid, int cmd, struct msqid_ds* buf);
struct mymsgbuf {
long mtype; //消息类型,正整数 char mtext[80]; };
void send_message(int qid, struct mymsgbuf *qbuf, long type, char *text); void read_message(int qid, struct mymsgbuf *qbuf, long type); void remove_queue(int qid);
int main(int argc, char *argv[]) {
key_t key;
int msgqueue_id;
struct mymsgbuf qbuf;
/* Create unique key via call to ftok() */
key = ftok(\/* key = 123456
/* Open the queue - create if necessary */
if((msgqueue_id = msgget(key, IPC_CREAT | 0666)) = = -1) //创建一个消息队列
{ //一般在服务器创建
perror(\ //客户端仅输
入权限
exit(1); } 。。。。。。。。 return(0);
}
void send_message(int qid, struct mymsgbuf *qbuf, long type, char *text) {
qbuf->mtype = type;
strcpy(qbuf->mtext, text);
if((msgsnd(qid, (struct msgbuf *)qbuf, strlen(qbuf->mtext)+1, 0)) = =-1) {
perror(\ exit(1); } }
void read_message(int qid, struct mymsgbuf *qbuf, long type) {
qbuf->mtype = type;
msgrcv(qid, (struct msgbuf *)qbuf, 80, type, 0); }
void remove_queue(int qid) {
msgctl(qid, IPC_RMID, 0); }
Note: 已逐渐淘汰。
4.4. 信号灯(一个计数器)
信号灯主要提供对进程间共享资源访问控制机制。相当于内存中的标志,进程可以根据它判定是否能够访问某些共享资源,同时,进程也可以修改该标志。除了用于访问控制外,还可用于进程同步。信号灯有以下两种类型:
二值信号灯:最简单的信号灯形式,信号灯的值只能取0或1,类似于互斥锁。
计算信号灯:信号灯的值可以取任意非负值(当然受内核本身的约束)。 对信号灯的操作有下面三种类型:
打开或创建信号灯、 信号灯值操作、 获得或设置信号灯属性
信号灯最简单的形式是某个可以被多个进程检验和设置(test&set)的内存单元。这个检验与设置操作对每个进程而言是不可中断或者说是一个原子性操作;一旦启动谁也终止不了。检验与设置操作的结果是信号灯当前值加1, 这个值可以是正数也可以是负数。根据这个操作的结果,进程可能可以一直睡眠到此信号灯的值被另一个进程更改为止。信号灯可用来实现临界区(critical region):某一时刻在此区域内的代码只能被一个进程执行。
如果你有多个协作进程从一个数据文件中读取与写入记录。有时你可能需要这些文件访问遵循严格的访问次序。 那么可在文件操作代码上使用一个初始值为1的信号灯,它带有两个信号灯操作,一个检验并对信号灯值减1,而另一个检验并加1。第一个访问文件的进程将试图将信号灯值减1,如果获得成功则信号灯值变成了 0。此进程于是开始使用这个数据文件,但是此时如果另一进程也想将信号灯值减1,则信号灯值将为-1,这次操作将会失败。它将挂起执行直到第一个进程完成对此数据文件的使用。此时这个等待进程将被唤醒,这次它对信号灯的操作将成功。
信号灯表Key1Key2Key30信号灯数组132345001323
#include
#include
int semget(key_t key, int nsems, int semflg); //
int semctl(int semid, int semnum, int cmd, union semnu arg);
int semop(int semid, struct sembuf* sops, unsigned nsops);//数组、个数
struct sembuf {
unsigned short sem_num; //序号 short sem_op; //操作,+1,-1 short sem_flg; //IPC_NOWAIT, SEM_UNDO等 };
Field Description
sem_num semaphore number sem_op semaphore operation sem_flg semaphore flags
union semun{ //一些参数 int val;
struct semid_ds *buf; ushort *array; }
删除信号灯:
union semun dummy; int semid; …..
semctl(semid,0,IPC_RMID,dummy); Ex:
#include
#include
#define SEM_NAME \
void sigint_handler(int); int semid;
unsigned int count;
struct sembuf psembuf,vsembuf;
int main(int argc,char*argv[]) {
int i,first,second; key_t key;
short initarray[2],outarray[2];
key=ftok(SEM_NAME,'a'); if(argc==1) {
signal(SIGINT,sigint_handler);
semid=semget(key,2,0777|IPC_CREAT); initarray[0]=initarray[1]=1;
semctl(semid,2,SETALL,initarray);//1,1 semctl(semid,2,GETALL,outarray);
printf(\ pause(); }
else if(argv[1][0]==0) {
first=0; second=1; } else {
first=1; second=0; }
semid=semget(key,2,0777); psembuf.sem_op=-1;
psembuf.sem_flg=SEM_UNDO; vsembuf.sem_op=1;
vsembuf.sem_flg=SEM_UNDO;
for(count=0;;count++) {
psembuf.sem_num=first;
semop(semid,&psembuf,1); //1—操作个数 psembuf.sem_num=second; semop(semid,&psembuf,1);
semctl(semid,2,GETALL,outarray);
printf(\