利用信号灯和共享内存实现循环倒置输出字符串

代码一:

#include <stdio.h>

#include <string.h>

#include <unistd.h>

#include <signal.h>

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/shm.h>

#include <sys/sem.h>

#include <errno.h>//改正过的循环倒置输出字符串************************************************

union semval

{

int val;

};

int main(int argc,char const* argv[])

{

key_t key;

key=ftok("./a.txt",'A');

if(key<0)

{

perror("ftok err");

return -1;

}printf("key=%#x\n",key);

/

//2.创建或打开信号灯集

int semid=semget(key,128,IPC_CREAT|IPC_EXCL|0666);

//key值//信号灯数//访问权限

if(semid < 0)

{

if(errno == EEXIST)

{

semid=semget(key,128,0666);

}else

{

perror("semget err.");

return -1;

}

}else //只有新建时需要初始化信号灯。

{

//3.初始化灯 灯有两个:编号0 1

union semval value;//需要先定义共用体变量形式union semval

value.val=1;

semctl(semid,0,SETVAL,value);

//信号灯id//信号灯编号//

value.val=0;

semctl(semid,1,SETVAL,value);

}

printf("***\n");

//4.申请资源 p

struct sembuf op;

//

int shmid=shmget(key,128,IPC_CREAT|IPC_EXCL|0666);

if(shmid<0)

{

if(errno==EEXIST)

{

shmid=shmget(key,128,0666);

}

else

{

perror("shmget err");

return -1;

}

}printf("shimd=%d\n",shmid);

char *sp=(char*)shmat(shmid,NULL,0);

if(sp==(char*)-1)//

{

perror("shmat err");

return -1;

}

strcpy(sp,"this is a interesting program");

//strcpy(sp,"hello world");

char *p=NULL,*q=NULL;

char temp;

while(1)

{

if(semctl(semid,0,GETVAL)>0)//0号灯:1//1号灯:0//根据0号灯数值判断进入if语句

{

//printf("0:%d 1:%d\n",semctl(semid,0,GETVAL),semctl(semid,1,GETVAL));

p=sp;

q=sp+strlen(sp)-1;

while(p<q)

{

*p^=*q;

*q^=*p;

*p++^=*q--;

}

//printf("%s\n",sp);

// op.sem_num=1;//1号灯

// op.sem_op=1;//申请

// op.sem_flg=0;//阻塞

// semop(semid,&op,1);

//sleep(1);

op.sem_num=0;//0号灯//

op.sem_op=-1;//申请

op.sem_flg=0;//阻塞

semop(semid,&op,1);//11111

op.sem_num=1;//1号灯//最后再更改信号灯1的值,防止8-shm-sem-w.c提前运行???

op.sem_op=1;//申请

op.sem_flg=0;//阻塞

semop(semid,&op,1);

//printf("0:%d 1:%d\n",semctl(semid,0,GETVAL),semctl(semid,1,GETVAL));

}

}

// 取消映射

shmdt(sp);

//销毁共享内存

shmctl(shmid,IPC_RMID,NULL);

return 0;

}

代码二:

#include <stdio.h>

#include <string.h>

#include <unistd.h>

#include <signal.h>

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/shm.h>

#include <sys/sem.h>//

#include <errno.h>

union semval

{

int val;

};

int main(int argc,char const* argv[])

{

key_t key;

key=ftok("./a.txt",'A');

if(key<0)

{

perror("ftok err");

return -1;

}printf("key=%#x\n",key);

/

//2.创建或打开信号灯集

int semid=semget(key,128,IPC_CREAT|IPC_EXCL|0666);

//key值//信号灯数//访问权限

if(semid < 0)

{

if(errno == EEXIST)

{

semid=semget(key,128,0666);

}else

{

perror("semget err.");

return -1;

}

}else //只有新建时需要初始化信号灯。

{

//3.初始化灯 灯有两个:编号0 1

union semval value;//需要先定义共用体变量形式union semval

value.val=1;

semctl(semid,0,SETVAL,value);

//信号灯id//信号灯编号//

value.val=0;

semctl(semid,1,SETVAL,value);

}

printf("***\n");

//4.申请资源 p

struct sembuf op;

//

int shmid=shmget(key,128,IPC_CREAT|IPC_EXCL|0666);//必须加IPC_EXCL,不然会

if(shmid<0)

{

if(errno==EEXIST)

{

shmid=shmget(key,128,0666);

}

else

{

perror("shmget err");

return -1;

}

}printf("shimd=%d\n",shmid);

char *sp=(char*)shmat(shmid,NULL,0);

if(sp==(char*)-1)//

{

perror("shmat err");

return -1;

}

//int i=0;

while(1)

{

if(semctl(semid,1,GETVAL)>0)//0:0//1:1//根据一号等数值判断

{

//printf("0号灯:%d 1号灯:%d\n",semctl(semid,0,GETVAL),semctl(semid,1,GETVAL));//测试神技

// op.sem_num=0;//0号灯

// op.sem_op=1;//申请

// op.sem_flg=0;//阻塞

// semop(semid,&op,1);//1111111

sleep(1);//此处的sleep是必须的

printf("%s\n",sp);

if(strncmp(sp,"quit",4)==0)

break;

op.sem_num=1;//1号灯

op.sem_op=-1;//申请

op.sem_flg=0;//阻塞

semop(semid,&op,1);

op.sem_num=0;//0号灯//

op.sem_op=1;//申请

op.sem_flg=0;//阻塞

semop(semid,&op,1);//这里的1表示要操作的信号灯数,不是信号灯的编号

//printf("0号灯:%d 1号灯:%d\n",semctl(semid,0,GETVAL),semctl(semid,1,GETVAL));

}

}

// 取消映射

shmdt(sp);

//销毁共享内存

shmctl(shmid,IPC_RMID,NULL);

return 0;

}

使用方式:

打开两个代码所在终端;

ipcs查看是否有正在使用的共享内存;

ipcrm -s 共享内存号//删除共享内存;

两个终端分别运行gcc 代码1.c和gcc代码2即可;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值