|
|
经常有人问IPC的问题,下面是一些简单的例子。有空看看!
System V信号量
[code:1:4e079536a0]
#define PERMS S_IRUSR|S_IWUSR
void init_semaphore_struct(struct sembuf *sem,int semnum,
int semop,int semflg)
{
/* 初始话信号灯结构 */
sem->sem_num=semnum;
sem->sem_op=semop;
sem->sem_flg=semflg;
}
int del_semaphore(int semid)
{
/* 信号灯并不随程序的结束而被删除,如果我们没删除的话(将1改为0)
可以用ipcs命令查看到信号灯,用ipcrm可以删除信号灯的
*/
#if 1
return semctl(semid,0,IPC_RMID);
#endif
}
int main(int argc,char **argv)
{
char buffer[MAX_CANON],*c;
int i,n;
int semid,semop_ret,status;
pid_t childpid;
struct sembuf semwait,semsignal;
if((argc!=2)||((n=atoi(argv[1]))<1))
{
fprintf(stderr,"Usage:%s number\n\a",argv[0]);
exit(1);
}
/* 使用IPC_PRIVATE 表示由系统选择一个关键字来创建 */
/* 创建以后信号灯的初始值为0 */
if((semid=semget(IPC_PRIVATE,1,PERMS))==-1)
{
fprintf(stderr,"[%d]:Acess Semaphore Error:%s\n\a",
getpid(),strerror(errno));
exit(1);
}
/* semwait是要求资源的操作(-1) */
init_semaphore_struct(&semwait,0,-1,0);
/* semsignal是释放资源的操作(+1) */
init_semaphore_struct(&semsignal,0,1,0);
/* 开始的时候有一个系统资源(一个标准错误输出) */
if(semop(semid,&semsignal,1)==-1)
{
fprintf(stderr,"[%d]:Increment Semaphore Error:%s\n\a",
getpid(),strerror(errno));
if(del_semaphore(semid)==-1)
fprintf(stderr,"[%d]:Destroy Semaphore Error:%s\n\a",
getpid(),strerror(errno));
exit(1);
}
/* 创建一个进程链 */
for(i=0;i if(childpid=fork()) break;
sprintf(buffer,"[i=%d]-->[Process=%d]-->[Parent=%d]-->[Child=%d]\n",
i,getpid(),getppid(),childpid);
c=buffer;
/* 这里要求资源,进入原子操作 */
while(((semop_ret=semop(semid,&semwait,1))==-1)&&(errno==EINTR));
if(semop_ret==-1)
{
fprintf(stderr,"[%d]:Decrement Semaphore Error:%s\n\a",
getpid(),strerror(errno));
}
else
{
while(*c!='\0')fputc(*c++,stderr);
/* 原子操作完成,赶快释放资源 */
while(((semop_ret=semop(semid,&semsignal,1))==-1)&&(errno==EINTR));
if(semop_ret==-1)
fprintf(stderr,"[%d]:Increment Semaphore Error:%s\n\a",
getpid(),strerror(errno));
}
/* 不能够在其他进程反问信号灯的时候,我们删除了信号灯 */
while((wait(&status)==-1)&&(errno==EINTR));
/* 信号灯只能够被删除一次的 */
if(i==1)
if(del_semaphore(semid)==-1)
fprintf(stderr,"[%d]:Destroy Semaphore Error:%s\n\a",
getpid(),strerror(errno));
exit(0);
}
[/code:1:4e079536a0]
SystemV消息队列
[code:1:4e079536a0]
#define MSG_FILE "server.c"
#define BUFFER 255
#define PERM S_IRUSR|S_IWUSR
struct msgtype {
long mtype;
char buffer[BUFFER+1];
};
int main()
{
struct msgtype msg;
key_t key;
int msgid;
if((key=ftok(MSG_FILE,'a'))==-1)
{
fprintf(stderr,"Creat Key Error:%s\a\n",strerror(errno));
exit(1);
}
if((msgid=msgget(key,PERM|IPC_CREAT|IPC_EXCL))==-1)
{
fprintf(stderr,"Creat Message Error:%s\a\n",strerror(errno));
exit(1);
}
while(1)
{
msgrcv(msgid,&msg,sizeof(struct msgtype),1,0);
fprintf(stderr,"Server Receive:%s\n",msg.buffer);
msg.mtype=2;
msgsnd(msgid,&msg,sizeof(struct msgtype),0);
}
exit(0);
}
--------------------------------------------------------------------------------
客户端(client.c)
#include
#include
#include
#include
#include
#include
#include
#include
#define MSG_FILE "server.c"
#define BUFFER 255
#define PERM S_IRUSR|S_IWUSR
struct msgtype {
long mtype;
char buffer[BUFFER+1];
};
int main(int argc,char **argv)
{
struct msgtype msg;
key_t key;
int msgid;
if(argc!=2)
{
fprintf(stderr,"Usage:%s string\n\a",argv[0]);
exit(1);
}
if((key=ftok(MSG_FILE,'a'))==-1)
{
fprintf(stderr,"Creat Key Error:%s\a\n",strerror(errno));
exit(1);
}
if((msgid=msgget(key,PERM))==-1)
{
fprintf(stderr,"Creat Message Error:%s\a\n",strerror(errno));
exit(1);
}
msg.mtype=1;
strncpy(msg.buffer,argv[1],BUFFER);
msgsnd(msgid,&msg,sizeof(struct msgtype),0);
memset(&msg,'\0',sizeof(struct msgtype));
msgrcv(msgid,&msg,sizeof(struct msgtype),2,0);
fprintf(stderr,"Client receive:%s\n",msg.buffer);
exit(0);
}
[/code:1:4e079536a0]
SystemV共享内存
[code:1:4e079536a0]
#define PERM S_IRUSR|S_IWUSR
int main(int argc,char **argv)
{
int shmid;
char *p_addr,*c_addr;
if(argc!=2)
{
fprintf(stderr,"Usage:%s\n\a",argv[0]);
exit(1);
}
if((shmid=shmget(IPC_PRIVATE,1024,PERM))==-1)
{
fprintf(stderr,"Create Share Memory Error:%s\n\a",strerror(errno));
exit(1);
}
if(fork())
{
p_addr=shmat(shmid,0,0);
memset(p_addr,'\0',1024);
strncpy(p_addr,argv[1],1024);
exit(0);
}
else
{
c_addr=shmat(shmid,0,0);
printf("Client get %s",c_addr);
exit(0);
}
}
[/code:1:4e079536a0]
| 一颗流星 回复于:2003-04-17 15:46:36
| 哈哈,太好了,结合实例理解加深不少呢!
我自己编程实现的都是单个进程间的:)
| | 蓝色键盘 回复于:2003-04-17 16:00:00
| SYSTEM V MSG
请求方程序
[code:1:ebf2406b93]
static struct msgbuf1{
long mtype;
char mtext[100];
} sndbuf, rcvbuf, *msgp ;
extern int errno;
main(int argc, char **argv)
{ int rtrn, msqid ;
char name[10];
double balance;
if (argc!=2){ fprintf(stderr,
"msgreq [01-99]\n"); exit(-1); }
if ( (msqid = msgget(0x888, IPC_CREAT|0660)) == -1 ){
fprintf(stderr, "msgget 888 failed !\n"); exit(-1);
}
msgp=&
sprintf(sndbuf.mtext,"%2.2s",argv[1]);
printf("输入4位帐号:");
scanf("%s",&sndbuf.mtext[2]);
sndbuf.mtext[6]=0;
msgp->mtype=666;
rtrn=msgsnd(msqid,msgp, strlen(sndbuf.mtext), 0);
if (rtrn==-1){
perror("msgsnd"); exit(-1);
}
msgp=&
fprintf(stderr,"等待后台数据处理进程的回答....");
rtrn=msgrcv(msqid,msgp, 100, atoi(argv[1]), 0);
if(rtrn==-1){ perror("msgrcv"); exit(-1); }
sscanf(rcvbuf.mtext,"%[^|]|%lf",name,&balance);
printf("\n姓名=%s\n",name);
printf("余额=%lf\n",balance);
}
[/code:1:ebf2406b93]
服务方程序
[code:1:ebf2406b93]
static struct msgbuf1{
long mtype;
char mtext[100];
} sndbuf, rcvbuf , *msgp;
extern int errno;
main()
{ int rtrn, msgqid ;
char strbuf[100];
if ( (msqid = msgget(0x888, IPC_CREAT|0600)) == -1 ){
fprintf(stderr, "msgget 888 failed !\n"); exit(-1);
}
while(1) {
msgp=&
fprintf(stderr,"等待前台进程的请求....");
rtrn=msgrcv(msqid, msgp, 100, 666 ,MSG_NOERROR);
if(rtrn==-1){ perror("msgrcv");exit(-1); }
msgp=&
sprintf(strbuf,"%2.2s\0",rcvbuf.mtext);
msgp->mtype=atoi(strbuf);
printf("\n输入帐号=%4.4s的帐户姓名:",&rcvbuf.mtext[2]);
scanf("%s",sndbuf.mtext);
strcat(sndbuf.mtext,"|");
printf("输入该帐户余额:");
scanf("%s",strbuf);
strcat(sndbuf.mtext,strbuf);
rtrn=msgsnd(msqid,msgp, strlen(sndbuf.mtext), 0);
if (rtrn==-1){ perror("msgsnd"); exit(-1); }
}
}
[/code:1:ebf2406b93]
| | 一颗流星 回复于:2003-04-18 09:50:26
| 我觉得这是个好东东,藏在后面怕有人看不见。所以
UP
| | superzhang 回复于:2003-04-18 10:12:31
| 往上顶一顶,不错,够热心的。
| | sz00 回复于:2003-04-25 14:34:07
| 太好了!
谢谢!
强烈UP!
| | walkandsee 回复于:2003-06-07 14:11:10
| good,up
| | towerjt 回复于:2003-06-08 10:44:32
| up
| | unixgood 回复于:2003-06-08 14:24:45
| sscanf(rcvbuf.mtext,"%[^|]|%lf",name,&balance);
这句话看不懂,,"%[^|]|%lf",是什么意思噢?
| | jsean 回复于:2003-06-12 11:22:11
| 好!
| | lozity 回复于:2005-05-24 14:44:49
| msgp=&是什么意思?
| | sea_stone 回复于:2005-05-27 12:16:04
| 不错,不错
学习中
| |
|