📄 chinaunix_net - unix进程之间的通信.htm
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!-- saved from url=(0041)http://www.chinaunix.net/jh/7/240959.html -->
<!-- Generated by LibHtt 2004-1-15 10:13:15 Templet source: /data0/chinaunix.net/cgisrc/do_html/viewtopics_jh.html Warnings and errors: 0--><HTML><HEAD><TITLE>ChinaUnix.net - UNIX进程之间的通信</TITLE>
<META content="text/html; charset=gb2312" http-equiv=Content-Type>
<META
content=Linux,Freebsd,Solaris,Sco,HP-UX,IBM-AIX,cisco,oracle,java,cgi,mysql,perl,Apache,proFTP,Sendmail,Qmail,DNS,Squid,Rsync,SSL
name=keywords>
<META content=中国UNIX技术社区 name=description>
<STYLE type=text/css>BODY {
FONT: 12pt 宋体
}
TH {
FONT: 12pt 宋体
}
INPUT {
FONT: 12pt 宋体
}
SELECT {
FONT: 12pt 宋体
}
TEXTAREA {
FONT: 12pt 宋体
}
SELECT {
FONT: 12pt 宋体
}
checkbox {
FONT: 12pt 宋体
}
BODY {
FONT-FAMILY: "宋体", "serif"; FONT-SIZE: 12pt
}
TD {
FONT-FAMILY: "宋体", "serif"; FONT-SIZE: 12pt
}
P {
FONT-SIZE: 9pt; LINE-HEIGHT: 150%
}
</STYLE>
<META content="MSHTML 5.00.3700.6699" name=GENERATOR></HEAD>
<BODY>
<DIV align=center>
<CENTER>
<TABLE border=0 cellPadding=0 cellSpacing=0 width="75%">
<TBODY>
<TR>
<TD height=45>
<P align=center><A href="http://www.chinaunix.net/"><IMG alt=ChinaUnix.net
border=0
src="ChinaUnix_net - UNIX进程之间的通信.files/logo.gif"></A> <B>CU-SCO
UNIX讨论区精华帖 </B></P></TD></TR>
<TR>
<TR>
<TD align=left height=40 vAlign=bottom><SMALL><A
href="http://www.chinaunix.net/">ChinaUnix.net</A> > <A
href="http://www.chinaunix.net/forum">论坛首页</A> > <A
href="http://www.chinaunix.net/jh">精华首页</A> > <A
href="http://www.chinaunix.net/jh/7">SCO UNIX精华区</A> > 正文
</SMALL></TD></TR>
<TR>
<TD bgColor=#49ade9 colSpan=5 height=2 width="100%"><IMG height=1
src="ChinaUnix_net - UNIX进程之间的通信.files/bline.gif"
width=1></TD></TR></TBODY></TABLE>
<TABLE border=0 cellPadding=0 cellSpacing=0 width="75%">
<TBODY>
<TR>
<TD align=middle bgColor=#edf0f5 height=40 vAlign=center><FONT
size=5><B>UNIX进程之间的通信</B></FONT></TD></TR>
<TR>
<TD align=middle bgColor=#edf0f5 height=20><SMALL>http://www.chinaunix.net
作者:<A
href="http://bbs.chinaunix.net/forum/profile.php?mode=viewprofile&u=17234"
target=_blank>xzh2002</A> 发表于:2004-01-10
15:00:32</FONT></SMALL></TD></TR>
<TR>
<TD align=middle bgColor=#edf0f5>
<TABLE align=center border=0 cellPadding=0 cellSpacing=0
style="BORDER-COLLAPSE: collapse; WORD-BREAK: break-all" width="90%">
<TBODY>
<TR>
<TD vAlign=top><BR>UNIX进程之间的通信
<BR><BR> 进程通讯是unix中很重要的知识。产生一个新的进程主要有以下3种方法: <BR><BR>1,fork调用;
<BR><BR>2,System调用; <BR><BR>3,Exec调用;
<BR><BR> 我们常说的进程通讯编程主要有以下3种方法: <BR><BR>1,Message queue队列编程;
<BR><BR>2,Tcp/IP socket编程; <BR><BR>3,共享内存编程; <BR><BR>一、进程调用
<BR><BR>1,产生进程Fork调用例子: <BR><BR>fork() <BR><BR>功能:创建一个新的进程.
<BR>语法:#include <unistd.h>
<BR>#include <sys/types.h> <BR>pid_t fork();
<BR>说明:本系统调用产生一个新的进程, 叫子进程, 是调用进程的一个复制品. 调用进程叫父进程, 子进程继承了父进程的几乎所有的属性:
<BR>. 实际UID,GID和有效UID,GID. <BR>. 环境变量. <BR>. 附加GID.
<BR>. 调用exec()时的关闭标志. <BR>. UID设置模式比特位.
<BR>. GID设置模式比特位. <BR>. 进程组号. <BR>. 会话ID.
<BR>. 控制终端. <BR>. 当前工作目录. <BR>. 根目录.
<BR>. 文件创建掩码UMASK. <BR>. 文件长度限制ULIMIT.
<BR>. 预定值, 如优先级和任何其他的进程预定参数, 根据种类不同决定是否可以继承.
<BR>. 还有一些其它属性. <BR><BR><BR>但子进程也有与父进程不同的属性:
<BR>. 进程号, 子进程号不同与任何一个活动的进程组号. <BR>. 父进程号.
<BR>. 子进程继承父进程的文件描述符或流时, 具有自己的一个拷贝并且与父进程和其它子进程共享该资源.
<BR>. 子进程的用户时间和系统时间被初始化为0. <BR>. 子进程的超时时钟设置为0.
<BR>. 子进程的信号处理函数指针组置为空. <BR>. 子进程不继承父进程的记录锁.
<BR>返回值: 调用成功则对子进程返回0, 对父进程返回子进程号, 这也是最方便的区分父子进程的方法. 若调用失败则返回-1给父进程,子进程不生成.
<BR><BR>2,产生进程system调用例子: <BR><BR>功能:产生一个新的进程, 子进程执行指定的命令.
<BR>语法:#include <stdio.h>
<BR>#include <stdlib.h> <BR>int system(string)
<BR>char *string;
<BR>说明:本调用将参数string传递给一个命令解释器(一般为sh)执行, 即string被解释为一条命令, 由sh执行该命令.若参数string为一个空指针则为检查命令解释器是否存在.该命令可以同命令行命令相同形式, 但由于命令做为一个参数放在系统调用中, 应注意编译时对特殊意义字符的处理. 命令的查找是按PATH环境变量的定义的. 命令所生成的后果一般不会对父进程造成影响.返回值:当参数为空指针时, 只有当命令解释器有效时返回值为非零.若参数不为空指针, 返回值为该命令的返回状态(同waitpid())的返回值. 命令无效或语法错误则返回非零值,所执行的命令被终止. 其他情况则返回-1.
<BR><BR><BR>[code:1:d22bc4f5e9]例子1:char command[81];
<BR>int i; <BR>for (i=1;i<8;i++) {
<BR>sprintf(command,"ps -t tty%02i",i);
<BR>system(command); <BR>} <BR><BR><BR>例子2:
<BR><BR>char befehl[200]; /* string buffer for csh command */
<BR>char *runserver = "hosts1"; /* server name */
<BR>short shift_act_l; /* currect shift number */
<BR>char shift_act_c[1];
<BR>char shift_beg[20]; /* shift begin */
<BR>char shift_end[20]; /* shift end */
<BR>.... <BR>T_report_p->shift_no='0';
<BR>memcpy(T_report_p->time_from,"yyyy-mm-dd hh:mi:ss",sizeof(T_report_p->time_from));
<BR>memcpy(T_report_p->time_to,"yyyy-mm-dd hh:mi:ss",sizeof(T_report_p->time_to));
<BR><BR>memset(befehl, '\0', sizeof(befehl));
<BR>sprintf (befehl, "rsh %s %sprot.sh '%s %s %c \"%19.19s\" \"%19.19s\" \"%9.9s\" 0' &",
<BR>runserver, <BR>REPORT_RSH_PATH, <BR>PROD_LOG,
<BR>DRUCKER_NAME_1, <BR>T_report_p->shift_no,
<BR>T_report_p->time_from, <BR>T_report_p->time_to,
<BR>T_report_p->coil_id ); <BR><BR>system (befehl);
<BR><BR>3,产生进程exec()调用例子: <BR><BR><BR>exec() <BR><BR>功能:执行一个文件
<BR>语法:#include <unistd.h>
<BR>int execl(path,arg0,...,argn,(char*)0)
<BR>char *path,*arg0,...,*argn; <BR>int execv(path,argv)
<BR>char *path,*argv[];
<BR>int execle(path,arg0,...,argn,(char*)0,envp)
<BR>char *path,*arg0,...,*argn,*envp[];
<BR>int execve(path,argv,envp)
<BR>char *path,*argv[],*envp[]; <BR>int execvp(file,argv)
<BR>char *file,*argv[];[/code:1:d22bc4f5e9]
<BR><BR>说明:这是一个系统调用族, 用于将一个新的程序调入本进程所占的内存, 并覆盖之, 产生新的内存进程映象. 新的程序可以是可执行文件或SHELL批命令.当C程序被执行时,是如下调用的:
<BR>main(int argc,char *argv[],char *envp[]);
<BR> argc是参数个数,是各个参数字符串指针数组,envp是新进程的环境变量字符串的指针数组.argc至少为1, argv[0]为程序文件名,所以,在上面的exec系统调用族中,path为新进程文件的路径名,file为新进程文件名,若file不是全路径名,系统调用会按PATH环境变量自动找对应的可执行文件运行.若新进程文件不是一个可执行的目标文件(如批处理文件),则execlp()和execvp()会将该文件内容作为一个命令解释器的标准输入形成system().arg0,...等指针指向'\0'结束的字符串,组成新进程的有效参数,且该参数列表以一个空指针结束.反过来,arg0至少必须存在并指向新进程文件名或路径名.同样,argv是字符串指针数组,argv[0]指向新进程文件名或路径名,并以一空指针结束.envp是一个字符串指针数组,以空指针结束,这些字符串组成新进程的环境.在调用这些系统调用前打开的文件指针对新进程来说也是打开的,除非它已定义了close-on-exec标志.打开的文件指针在新进程中保持不变,所有相关的文件锁也被保留.调用进程设置并正被捕俘的信号在新进程中被恢复为缺省设置,其它的则保持不变.新进程启动时按文件的SUID和SGID设置定义文件的UID和GID为有效UID和GID.新进程还继承了如下属性:
<BR>. 附加GID. <BR>. 进程号. <BR>. 父进程号. <BR>. 进程组号.
<BR>. 会话号. <BR>. 控制终端. <BR>. alarm时钟信号剩下的时间.
<BR>. 当前工作目录. <BR>. 根目录. <BR>. 文件创建掩码.
<BR>. 资源限制. <BR>. 用户时间,系统时间,子进程用户时间,子进程系统时间.
<BR>. 记录锁. <BR>. 进程信号掩码. <BR>. 信号屏蔽. <BR>. 优先级.
<BR>. 预定值.
<BR> 调用成功后,系统调用修改新进程文件的最新访问时间.返回值:该系统调用一般不会有成功返回值, 因为原来的进程已荡然无存.
<BR>例子:printf("now this process will be ps command\n");
<BR>execl("/bin/ps","ps","-ef",NULL); <BR><BR>二、进程通讯编程
<BR><BR>[code:1:d22bc4f5e9]1,Message queue队列编程例子
<BR><BR>/*****************************************************************************
<BR>Excerpt from "Linux Programmer's Guide - Chapter 6"
<BR>(C)opyright 1994-1995, Scott Burkett
<BR>*****************************************************************************
<BR>MODULE: msgtool.c
<BR>*****************************************************************************
<BR>A command line tool for tinkering with SysV style Message Queues
<BR>*****************************************************************************/
<BR><BR>#include <stdio.h>
<BR>#include <stdlib.h> <BR>#include <ctype.h>
<BR>#include <sys/types.h>
<BR>#include <sys/ipc.h>
<BR>#include <sys/msg.h>
<BR><BR>#define MAX_SEND_SIZE 80
<BR><BR>struct mymsgbuf { <BR>long mtype;
<BR>char mtext[MAX_SEND_SIZE]; <BR>};
<BR><BR>void send_message(int qid, struct mymsgbuf *qbuf, long type, char *text);
<BR>void read_message(int qid, struct mymsgbuf *qbuf, long type);
<BR>void remove_queue(int qid);
<BR>void change_queue_mode(int qid, char *mode);
<BR>void usage(void);
<BR><BR><BR>int main(int argc, char *argv[])
<BR>{ <BR>key_t key; <BR>int msgqueue_id;
<BR>struct mymsgbuf qbuf; <BR><BR>if(argc == 1)
<BR>usage();
<BR><BR>/* Create unique key via call to ftok() */
<BR>/* key = ftok(".", 'w'); */
<BR>key = 123456; <BR>printf("key=%d\n",key);
<BR>key=IPC_PRIVATE;
<BR>/* Open the queue - create if necessary */
<BR><BR>if((tolower(argv[1][0]))!='s') <BR>{
<BR>if((msgqueue_id = msgget(key, IPC_CREAT|0666)) == -1) {
<BR>perror("msgget"); <BR>exit(1); <BR>}
<BR>printf("msgqueue_id=%d\n",msgqueue_id); <BR>}
<BR><BR>switch(tolower(argv[1][0])) <BR>{
<BR>case 's': send_message(atoi(argv[4]), (struct mymsgbuf *)&qbuf,
<BR>atol(argv[2]), argv[3]); <BR>break;
<BR>case 'r': read_message(msgqueue_id, &qbuf, atol(argv[2]));
<BR>break;
<BR>case 'd': remove_queue(atoi(argv[2]));
<BR>remove_queue(msgqueue_id); <BR>break;
<BR>case 'm': change_queue_mode(msgqueue_id, argv[2]);
<BR>break; <BR><BR>default: usage(); <BR><BR>}
<BR><BR>return(0); <BR>}
<BR><BR>void send_message(int qid, struct mymsgbuf *qbuf, long type, char *text)
<BR>{ <BR>printf("msgqueue_id=%d\n",qid);
<BR>/* Send a message to the queue */
<BR>printf("Sending a message ...\n");
<BR>qbuf->mtype = type;
<BR>strcpy(qbuf->mtext, text);
<BR>printf(" Type: %ld Text: %s\n", qbuf->mtype, qbuf->mtext);
<BR><BR>if((msgsnd(qid, (struct msgbuf *)qbuf,
<BR>strlen(qbuf->mtext)+1, 0)) ==-1) <BR>{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -