您的位置:首页 > 运维架构 > Linux

linux中关于IPC(一部分涉及读者写者问题)

2009-10-07 20:42 489 查看
sem的相关用法

一个简单的例子:
产生一个信号集,把信号集的id输出
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <stdio.h>
int main()
{
key_t unique_key;
int id;
struct sembuf lock_it;
//union semun options;
int i;
unique_key=ftok(".",'a');
id=semget(unique_key,1,IPC_CREAT | IPC_EXCL | 0666);
printf("the sem id is %d/n",id);
}
注:
1。创建IPC需要获取一个系统唯一的关键字:key,如:
unique_key=ftok(".",'a');
2。shmget是获得信号集的API函数,具体细节可以复习IPC相关知识。


共享内存的使用.

下面的例子是一个读者写着问题的解决方案

这是一个读者,写者问题
程序中读者和写着读取和写入的片段是一段共享内存
对共享内存的读写操作就像对程序的堆栈操作一样,
shmat会返回一个字符指针的,提供读写的一篇区域
#include <stdio.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <stdlib.h>
#define SHMKEY (key_t)0x10
#define SEMKEY (key_t)0x15
#define IFLAGS (IPC_CREAT | IPC_EXCL)
#define ERR ((struct databuf*)-1)
typedef char string[50];
struct databuf
{
int nbuf;    //number of string buf
string buf[10];
};
static semid,shmid;
void fatal(char *mes)
{
perror(mes);
exit(1);
}
void getseg(struct databuf **p)
{
if(shmid=shmget(SHMKEY,sizeof(struct databuf),0666|IFLAGS)==-1)
fatal("shmget");
//link to data pointer
if((*p=(struct databuf *)(shmat(shmid,0,0)))==ERR)
fatal("shmat");
}
int getsem()
{
//create semaphore
if((semid=semget(SEMKEY,1,IFLAGS | 0666))==-1)
fatal("semget");

if(semctl(semid,0,SETVAL,0)==-1)
fatal("semctl");

return semid;
}
void myremove()
{
if(semctl(semid,0,IPC_RMID,NULL)==-1)
fatal("semclt");

if(shmctl(shmid,IPC_RMID,NULL)==-1)
fatal("shmctl");
}
void reader(int semid,struct databuf *dbuf)
{
printf("This is reader process(son process)/n");
struct sembuf p={0,-1,0};
struct sembuf v={0,1,0};
char judge;
while(1)
{
if(semop(semid,&p,1)==-1)
fatal("semop");
if(dbuf->nbuf==0)
{
fprintf(stderr,"There is no data in the shared memory!/n");
semop(semid,&v,1);
continue;
}
else
{
printf("%s",dbuf->buf[--dbuf->nbuf]);
}
if(semop(semid,&v,1)==-1)
fatal("semop");
/*
printf("Continue to read?(y/n)/n");
scanf("%c",&judge);
if(judge=='Y' | judge=='y')
continue;
else
berak;*/
}

}
void writer(int semid,struct databuf *dbuf)
{
printf("This is writer process(father process)/n");
struct sembuf p={0,-1,0};
struct sembuf v={0,1,0};
char judge;
while(1)
{
//wait
if(semop(semid,&p,1)==-1)
fatal("semop");
//whether the buf full?
if(dbuf->nbuf==10)
{
fprintf(stderr,"The buf is full!/n");
semop(semid,&v,1);
continue;
}
else
{
printf("Please put data to the buf:/n");
scanf("%s",dbuf->buf[dbuf->nbuf++]);
}
if(semop(semid,&v,1)==-1)
{
fatal("semop");
}
/*
//continue to write
printf("Continue to write?(y/n)/n");
scanf("%c",&judge);
if(judge=='Y' | judge=='y')
continue;
else
exit(0); */
}
}
int main()
{
int pid;
struct databuf *buf;
//myremove();
//initial semaphore set
semid=getsem();

//create and link to shared memory
getseg(&buf);  //take care

switch(pid=fork())
{
case -1:
fatal("fork()");
case 0:
writer(semid,buf);
myremove();
break;
default:
reader(semid,buf);
break;
}
// remove();
exit(0);
}


管道机制

无名管道

父子进程之间通过无名管道通信

pipe函数创建一个无名管道,参数为一个大小为2的int数组
管道有两个端口,一个为读端口,一个为些端口
其中fd[0]为读端口,fd[1]为写端口
下面的程序子进程向父进程说了一生:“hello world!”
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
int main()
{
int fd[2],nbytes;
pid_t child_pid;
char string[]="hello,world!/n";
char read_buff[80];

pipe(fd);
if((child_pid=fork())==-1)
{
perror("fork");
exit(1);
}
//child process write to pipe
//father process read the pipe
if(child_pid==0)
{
close(fd[0]);
write(fd[1],string,strlen(string));
_exit(0);
}
else
{
close(fd[1]);
nbytes=read(fd[0],read_buff,80);
printf("Recieve string:%s/n",read_buff);
}

return 0;
}


命名管道

管道还有另外一种类型,那就是命名管道,命名管道创建之后,
我们可以相使用任何其他文件一样,对命名管道进行读写操作
下面的例子,程序一创建了一个命名管道,在从其中读取数据
程序二向这个命名管道中写入数据,从而达到两个进程之间的
通信的目的
程序一:
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <unistd.h>
#include <linux/stat.h>
#define FIFO_FILE "sampleFIFO"
int main()
{
FILE *fp;
char readbuf[80];

//create the FIFO if id does not exist
umask(0);

//create the FIFO in the file system
mknod(FIFO_FILE,S_IFIFO|0666,0);

while(1)
{
//open the FIFO
fp=fopen(FIFO_FILE,"r");

fgets(readbuf,80,fp);
printf("Receive string:%s/n",readbuf);
//close the FIFO
fclose(fp);
}
return 0;
}
程序二:
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <unistd.h>
#include <linux/stat.h>
#define FIFO_FILE "sampleFIFO"
int main()
{
FILE *fp;
char readbuf[80];

//create the FIFO if id does not exist
umask(0);

//create the FIFO in the file system
mknod(FIFO_FILE,S_IFIFO|0666,0);

while(1)
{
//open the FIFO
fp=fopen(FIFO_FILE,"r");

fgets(readbuf,80,fp);
printf("Receive string:%s/n",readbuf);
//close the FIFO
fclose(fp);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: