📄 [ 永远的unix linux下c语言编程--进程通信、消息管理 ].htm
字号:
<BR>while(((semop_ret=semop(semid,&semsignal,1))==-1)&&(errno==EINTR));
<BR>if(semop_ret==-1)
<BR>
fprintf(stderr,"[%d]:Increment Semaphore Error:%s\n\a",
<BR> getpid(),strerror(errno));
<BR> } <BR><BR>/* 不能够在其他进程反问信号灯的时候,我们删除了信号灯 */
<BR>while((wait(&status)==-1)&&(errno==EINTR)); <BR>/*
信号灯只能够被删除一次的 */ <BR>if(i==1) <BR> if(del_semaphore(semid)==-1)
<BR> fprintf(stderr,"[%d]:Destroy Semaphore Error:%s\n\a",
<BR> getpid(),strerror(errno));
<BR>exit(0); <BR>}
<BR><BR>信号灯的主要用途是保护临界资源(在一个时刻只被一个进程所拥有).
<BR>3。SystemV消息队列 为了便于进程之间通信,我们可以使用管道通信 SystemV也提供了一些函数来实现进程的通信.这就是消息队列.
<BR><BR> #include <SYS types.h>
<BR> #include <SYS ipc.h>
<BR> #include <SYS msg.h>
<BR><BR> int msgget(key_t key,int msgflg);
<BR> int msgsnd(int msgid,struct msgbuf *msgp,int msgsz,int msgflg);
<BR> int msgrcv(int msgid,struct msgbuf *msgp,int msgsz,
<BR>long msgtype,int msgflg);
<BR> int msgctl(Int msgid,int cmd,struct msqid_ds *buf);
<BR><BR>struct msgbuf {
<BR>long msgtype; /* 消息类型 */ <BR>....... /*
其他数据类型 */ <BR>}
<BR><BR>msgget函数和semget一样,返回一个消息队列的标志.msgctl和semctl是对消息进行控制. msgsnd和msgrcv函数是用来进行消息通讯的.msgid是接受或者发送的消息队列标志. msgp是接受或者发送的内容.msgsz是消息的大小. 结构msgbuf包含的内容是至少有一个为msgtype.其他的成分是用户定义的.对于发送函数msgflg指出缓冲区用完时候的操作.接受函数指出无消息时候的处理.一般为0. 接收函数msgtype指出接收消息时候的操作.
<BR>如果msgtype=0,接收消息队列的第一个消息.大于0接收队列中消息类型等于这个值的第一个消息.小于0接收消息队列中小于或者等于msgtype绝对值的所有消息中的最小一个消息. 我们以一个实例来解释进程通信.下面这个程序有server和client组成.先运行服务端后运行客户端.
<BR>服务端 server.c <BR><BR>#include <STDIO.H>
<BR>#include <STRING.H> <BR>#include <STDLIB.H>
<BR>#include <ERRNO.H> <BR>#include <UNISTD.H>
<BR>#include <SYS types.h> <BR>#include <SYS ipc.h>
<BR>#include <SYS stat.h> <BR>#include <SYS msg.h>
<BR><BR>#define MSG_FILE "server.c" <BR>#define
BUFFER 255 <BR>#define PERM
S_IRUSR|S_IWUSR <BR><BR>struct msgtype {
<BR>long mtype; <BR>char buffer[BUFFER+1]; <BR>};
<BR><BR>int main() <BR>{
<BR> struct msgtype msg;
<BR> key_t key;
<BR> int msgid; <BR>
<BR> if((key=ftok(MSG_FILE,'a'))==-1)
<BR> {
<BR>fprintf(stderr,"Creat Key Error:%s\a\n",strerror(errno));
<BR>exit(1); <BR> } <BR>
<BR> if((msgid=msgget(key,PERM|IPC_CREAT|IPC_EXCL))==-1)
<BR> {
<BR>fprintf(stderr,"Creat Message Error:%s\a\n",strerror(errno));
<BR>exit(1); <BR> } <BR>
<BR> while(1) <BR> {
<BR>msgrcv(msgid,&msg,sizeof(struct msgtype),1,0);
<BR>fprintf(stderr,"Server Receive:%s\n",msg.buffer);
<BR>msg.mtype=2;
<BR>msgsnd(msgid,&msg,sizeof(struct msgtype),0);
<BR> } <BR> exit(0); <BR>}
<BR><BR><BR>--------------------------------------------------------------------------------
<BR><BR>客户端(client.c) <BR><BR>#include <STDIO.H>
<BR>#include <STRING.H> <BR>#include <STDLIB.H>
<BR>#include <ERRNO.H> <BR>#include <SYS types.h>
<BR>#include <SYS ipc.h> <BR>#include <SYS msg.h>
<BR>#include <SYS stat.h> <BR>#define MSG_FILE
"server.c" <BR>#define BUFFER 255
<BR>#define PERM S_IRUSR|S_IWUSR
<BR><BR>struct msgtype { <BR>long mtype;
<BR>char buffer[BUFFER+1]; <BR>};
<BR><BR>int main(int argc,char **argv) <BR>{
<BR> struct msgtype msg;
<BR> key_t key;
<BR> int msgid; <BR>
<BR> if(argc!=2) <BR> {
<BR>fprintf(stderr,"Usage:%s string\n\a",argv[0]); <BR>exit(1);
<BR> }
<BR><BR> if((key=ftok(MSG_FILE,'a'))==-1)
<BR> {
<BR>fprintf(stderr,"Creat Key Error:%s\a\n",strerror(errno));
<BR>exit(1); <BR> } <BR>
<BR> if((msgid=msgget(key,PERM))==-1)
<BR> {
<BR>fprintf(stderr,"Creat Message Error:%s\a\n",strerror(errno));
<BR>exit(1); <BR> }
<BR><BR> msg.mtype=1;
<BR> strncpy(msg.buffer,argv[1],BUFFER);
<BR> msgsnd(msgid,&msg,sizeof(struct msgtype),0);
<BR> memset(&msg,'\0',sizeof(struct msgtype));
<BR> msgrcv(msgid,&msg,sizeof(struct msgtype),2,0);
<BR> fprintf(stderr,"Client receive:%s\n",msg.buffer);
<BR> exit(0); <BR>}
<BR><BR>注意服务端创建的消息队列最后没有删除,我们要使用ipcrm命令来删除的.
<BR>4。SystemV共享内存 还有一个进程通信的方法是使用共享内存.SystemV提供了以下几个函数以实现共享内存.
<BR><BR>#include <SYS types.h> <BR>#include <SYS ipc.h>
<BR>#include <SYS shm.h>
<BR><BR>int shmget(key_t key,int size,int shmflg);
<BR>void *shmat(int shmid,const void *shmaddr,int shmflg);
<BR>int shmdt(const void *shmaddr);
<BR>int shmctl(int shmid,int cmd,struct shmid_ds *buf);
<BR><BR>shmget和shmctl没有什么好解释的.size是共享内存的大小. shmat是用来连接共享内存的.shmdt是用来断开共享内存的.不要被共享内存词语吓倒,共享内存其实很容易实现和使用的.shmaddr,shmflg我们只要用0代替就可以了.在使用一个共享内存之前我们调用shmat得到共享内存的开始地址,使用结束以后我们使用shmdt断开这个内存.
<BR><BR>#include <STDIO.H> <BR>#include <STRING.H>
<BR>#include <ERRNO.H> <BR>#include <UNISTD.H>
<BR>#include <SYS stat.h> <BR>#include <SYS types.h>
<BR>#include <SYS ipc.h> <BR>#include <SYS shm.h>
<BR><BR>#define PERM S_IRUSR|S_IWUSR
<BR><BR>int main(int argc,char **argv) <BR>{
<BR> <BR> int shmid;
<BR> char *p_addr,*c_addr; <BR> if(argc!=2)
<BR> { <BR>fprintf(stderr,"Usage:%s\n\a",argv[0]);
<BR>exit(1); <BR> }
<BR><BR> if((shmid=shmget(IPC_PRIVATE,1024,PERM))==-1)
<BR> {
<BR>fprintf(stderr,"Create Share Memory Error:%s\n\a",strerror(errno));
<BR>exit(1); <BR> } <BR> if(fork())
<BR> { <BR>p_addr=shmat(shmid,0,0);
<BR>memset(p_addr,'\0',1024); <BR>strncpy(p_addr,argv[1],1024);
<BR>exit(0); <BR> } <BR> else <BR> {
<BR>c_addr=shmat(shmid,0,0);
<BR>printf("Client get %s",c_addr); <BR>exit(0);
<BR> } <BR>}
<BR><BR>这个程序是父进程将参数写入到共享内存,然后子进程把内容读出来.最后我们要使用ipcrm释放资源的.先用ipcs找出ID然后用ipcrm shm ID删除.
<BR>后记:
<BR>进程通信(IPC)是网络程序的基础,在很多的网络程序当中会大量的使用进程通信的概念和知识.其实进程通信是一件非常复杂的事情,我在这里只是简单的介绍了一下.如果你想学习进程通信的详细知识,最好的办法是自己不断的写程序和看联机手册.现在网络上有了很多的知识可以去参考.可惜我看到的很多都是英文编写的.如果你找到了有中文的版本请尽快告诉我.谢谢!
<BR><BR><BR> <BR> <BR>(<A
href="http://www.fanqiang.com/">http://www.fanqiang.com/</A>)
</FONT> 进入【<A
href="http://www.chinaunix.net/">UNIX论坛</A>】 </TD></TR>
<TR>
<TD>
<HR>
</TD></TR>
<TR>
<TD><B>相关文章</B> </TD></TR>
<TR>
<TD><A
href="http://www.fanqiang.com/a4/b2/20010508/113838.html">Linux下C语言编程--线程操作</A>
<SMALL>(2001-05-08 11:43:15)</SMALL></FONT><BR><A
href="http://www.fanqiang.com/a4/b2/20010508/113803.html">Linux下C语言编程--进程通信、消息管理</A>
<SMALL>(2001-05-08 11:38:03)</SMALL></FONT><BR><A
href="http://www.fanqiang.com/a4/b2/20010508/113528.html">Linux下C语言编程--信号处理函数</A>
<SMALL>(2001-05-08 11:35:28)</SMALL></FONT><BR><A
href="http://www.fanqiang.com/a4/b2/20010508/113412.html">Linux下C语言编程--时间概念</A>
<SMALL>(2001-05-08 11:34:12)</SMALL></FONT><BR><A
href="http://www.fanqiang.com/a4/b2/20010508/113315.html">Linux下C语言编程--文件的操作</A>
<SMALL>(2001-05-08 11:33:15)</SMALL></FONT><BR><A
href="http://www.fanqiang.com/a4/b2/20010508/113230.html">Linux下C语言编程--进程的创建</A>
<SMALL>(2001-05-08 11:32:30)</SMALL></FONT><BR><A
href="http://www.fanqiang.com/a4/b2/20010508/113129.html">Linux下C语言编程--基础知识</A>
<SMALL>(2001-05-08 11:31:29)</SMALL></FONT><BR></TD></TR>
<TR>
<TR>
<TD></TD></TR>
<TR>
<TD> </TD></TR></TBODY></TABLE></TD></TR>
<TR>
<TD bgColor=#d09f0d colSpan=5 height=2 width="100%"><IMG height=1
src="[ 永远的UNIX Linux下C语言编程--进程通信、消息管理 ].files/c.gif" width=1></TD></TR>
<TR>
<TD colSpan=5 height=40 vAlign=top width="100%">
<P align=center><FONT color=#ffffff>★ 樊强制作 欢迎分享 ★
</FONT></P></TD></TR></TBODY></TABLE></CENTER></DIV></BODY></HTML>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -