⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tx.c

📁 Linux下,模拟信号互斥,程序很短小精悍,仔细读读可以加深对进程间通信的理解
💻 C
字号:
 #include<stdio.h>
 #include<stdlib.h>
 #include<string.h>
 #include<unistd.h>
 #include<sys/types.h>
 #include<linux/shm.h>
 #include<linux/sem.h>
// #define BUFSIZE 10    //定义缓冲区大小

 int empty,full,mutex;  //定义内存空、满、互斥三个信号量
 int producer,customerA,customerB;  //声明生产者消费者
 int shmid1,shmid2,i;           //定义共享存储区的描述符
 int set=0;                       //缓冲区号的计数


 int main()
 {
   int *array,*get;         //虚拟地址空间
   struct sembuf P,V;               //定义P、V操作所用的数据结构
   union semun arg;                 //定义给信号量赋初值的参数数据结构
   shmid1=shmget(IPC_PRIVATE,5,0666|IPC_CREAT);  //创建一共享内存
   shmid2=shmget(IPC_PRIVATE,1,0666|IPC_CREAT);  //创建第二个共享内存
   array=(int*)shmat(shmid1,0,0);    //附接到共享内存上(数值型)
   get=(int*)shmat(shmid2,0,0);
   empty=semget(IPC_PRIVATE,1,0666|IPC_CREAT); //创建一个新的信号量empty
   arg.val=5;                                 //为空信号量赋值5
   semctl(empty,0,SETVAL,arg);
   full=semget(IPC_PRIVATE,1,0666|IPC_CREAT); 
   arg.val=0;                                 //为满信号量赋值0
   semctl(full,0,SETVAL,arg);
   mutex=semget(IPC_PRIVATE,1,0666|IPC_CREAT);
   arg.val=1;                                 //设置互斥信号量1
   semctl(mutex,0,SETVAL,arg);
   /*定义信号量的P操作*/
   P.sem_num=0; //第一个信号量
   P.sem_op=-1; //负数:则相当于P操作
   P.sem_flg=SEM_UNDO;  //指明内核为信号量操作保留恢复值

   /*定义信号量的V操作*/
   V.sem_num=0;
   V.sem_op=1;  //正数:此时相当于V操作
   V.sem_flg=SEM_UNDO;

      while((producer=fork())==-1);  //利用fork()函数创建生产者子进程
	  if(producer==0)
		{
		   for(i=0;i<10;i++)
			{
			   semop(empty,&P,1);   //判断共享区空否
			   semop(mutex,&P,1);  //进入临界区前执行P操作(使用方法同P课上讲解的操作)
 			   printf("producer inputs data:%d\n",i);
                           array[set]=i;
			   set++;	         //计数
                           sleep(1);
			   semop(mutex,&V,1);  //出临界区执行V操作(使用方法同V课上讲解的操作)
			   semop(full,&V,1);	
			}
			exit(0);               //生产者子进程终止
		 }
	else{
		while((customerA=fork())==-1);//创建消费者A进程
		if(customerA==0)
			{
			   for(i=0;i<10;i++)
				{
				  sleep(1);     
				  semop(full,&P,1); //判断共享区满否
				  semop(mutex,&P,1);//进入临界区前执行P互斥操作(使用方法同P课上讲解的操作)
				  printf("customerA:%d\n",array[*get]);
				  (*get)++;
				  sleep(1);
				  semop(mutex,&V,1);
				  semop(empty,&V,1);
				}
			  exit(0);   			//消费者A子进程终止	
			}
		else{
			while((customerB=fork())==-1);//创建消费者B进程
			    if(customerB==0)
				{
				   for(i=0;i<10;i++)
					{
					   sleep(1);
					   semop(full,&P,1);
					   semop(mutex,&P,1);
					   printf("customerB:%d\n",array[*get]);
					   (*get)++;
					   sleep(1);
					   semop(mutex,&V,1);
					   semop(empty,&V,1);
					}
				exit(0);                //消费者B子进程终止
				  }
			   else{
                              wait(0);	          //等待子进程结束
				  wait(0);
			         wait(0);
                              shmdt(array);	   //将共享内存从进程的地址空间1断开						
				  shmctl(shmid1,IPC_RMID,0);//撤消共享存储区
				  shmdt(get);      //将共享内存从进程的地址空间2断开
 				  shmctl(shmid2,IPC_RMID,0);
                                  /*撤消三个信号量*/
			         semctl(empty,IPC_RMID,0);
 				  semctl(full,IPC_RMID,0);
				  semctl(mutex,IPC_RMID,0);
				  exit(0);
				}
		    }
              }
}

student@saturn1:~$ gcc -o 2 2.c
student@saturn1:~$ ./2
producer inputs data:0
producer inputs data:1
customerA:0
producer inputs data:2

student@saturn1:~$ ./
bash: ./: is a directory
student@saturn1:~$ ./2
producer inputs data:0
producer inputs data:1
customerA:0
producer inputs data:2
customerB:1
producer inputs data:3
customerA:2
producer inputs data:4
customerB:3
producer inputs data:5
customerA:4
producer inputs data:6
customerB:5
producer inputs data:7
customerA:6
producer inputs data:8
customerB:7
producer inputs data:9
customerA:8
customerB:9

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -