分享
 
 
 

UNIX进程之间的通信

王朝system·作者佚名  2006-11-24
窄屏简体版  字體: |||超大  

UNIX进程之间的通信

进程通讯是unix中很重要的知识。产生一个新的进程主要有以下3种方法:

1,fork调用;

2,System调用;

3,Exec调用;

我们常说的进程通讯编程主要有以下3种方法:

1,Message queue队列编程;

2,Tcp/IP socket编程;

3,共享内存编程;

一、进程调用

1,产生进程Fork调用例子:

fork()

功能:创建一个新的进程.

语法:#include <unistd.h>

#include <sys/types.h>

pid_t fork();

说明:本系统调用产生一个新的进程, 叫子进程, 是调用进程的一个复制品. 调用进程叫父进程, 子进程继承了父进程的几乎所有的属性:

. 实际UID,GID和有效UID,GID.

. 环境变量.

. 附加GID.

. 调用exec()时的关闭标志.

. UID设置模式比特位.

. GID设置模式比特位.

. 进程组号.

. 会话ID.

. 控制终端.

. 当前工作目录.

. 根目录.

. 文件创建掩码UMASK.

. 文件长度限制ULIMIT.

. 预定值, 如优先级和任何其他的进程预定参数, 根据种类不同决定是否可以继承.

. 还有一些其它属性.

但子进程也有与父进程不同的属性:

. 进程号, 子进程号不同与任何一个活动的进程组号.

. 父进程号.

. 子进程继承父进程的文件描述符或流时, 具有自己的一个拷贝并且与父进程和其它子进程共享该资源.

. 子进程的用户时间和系统时间被初始化为0.

. 子进程的超时时钟设置为0.

. 子进程的信号处理函数指针组置为空.

. 子进程不继承父进程的记录锁.

返回值: 调用成功则对子进程返回0, 对父进程返回子进程号, 这也是最方便的区分父子进程的方法. 若调用失败则返回-1给父进程,子进程不生成.

2,产生进程system调用例子:

功能:产生一个新的进程, 子进程执行指定的命令.

语法:#include <stdio.h>

#include <stdlib.h>

int system(string)

char *string;

说明:本调用将参数string传递给一个命令解释器(一般为sh)执行, 即string被解释为一条命令, 由sh执行该命令.若参数string为一个空指针则为检查命令解释器是否存在.该命令可以同命令行命令相同形式, 但由于命令做为一个参数放在系统调用中, 应注意编译时对特殊意义字符的处理. 命令的查找是按PATH环境变量的定义的. 命令所生成的后果一般不会对父进程造成影响.返回值:当参数为空指针时, 只有当命令解释器有效时返回值为非零.若参数不为空指针, 返回值为该命令的返回状态(同waitpid())的返回值. 命令无效或语法错误则返回非零值,所执行的命令被终止. 其他情况则返回-1.

[code:1:d22bc4f5e9]例子1:char command[81];

int i;

for (i=1;i<8;i++) {

sprintf(command,"ps -t tty%02i",i);

system(command);

}

例子2:

char befehl[200]; /* string buffer for csh command */

char *runserver = "hosts1"; /* server name */

short shift_act_l; /* currect shift number */

char shift_act_c[1];

char shift_beg[20]; /* shift begin */

char shift_end[20]; /* shift end */

....

T_report_p->shift_no='0';

memcpy(T_report_p->time_from,"yyyy-mm-dd hh:mi:ss",sizeof(T_report_p->time_from));

memcpy(T_report_p->time_to,"yyyy-mm-dd hh:mi:ss",sizeof(T_report_p->time_to));

memset(befehl, '\0', sizeof(befehl));

sprintf (befehl, "rsh %s %sprot.sh '%s %s %c \"%19.19s\" \"%19.19s\" \"%9.9s\" 0' &",

runserver,

REPORT_RSH_PATH,

PROD_LOG,

DRUCKER_NAME_1,

T_report_p->shift_no,

T_report_p->time_from,

T_report_p->time_to,

T_report_p->coil_id );

system (befehl);

3,产生进程exec()调用例子:

exec()

功能:执行一个文件

语法:#include <unistd.h>

int execl(path,arg0,...,argn,(char*)0)

char *path,*arg0,...,*argn;

int execv(path,argv)

char *path,*argv[];

int execle(path,arg0,...,argn,(char*)0,envp)

char *path,*arg0,...,*argn,*envp[];

int execve(path,argv,envp)

char *path,*argv[],*envp[];

int execvp(file,argv)

char *file,*argv[];[/code:1:d22bc4f5e9]

说明:这是一个系统调用族, 用于将一个新的程序调入本进程所占的内存, 并覆盖之, 产生新的内存进程映象. 新的程序可以是可执行文件或SHELL批命令.当C程序被执行时,是如下调用的:

main(int argc,char *argv[],char *envp[]);

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.新进程还继承了如下属性:

. 附加GID.

. 进程号.

. 父进程号.

. 进程组号.

. 会话号.

. 控制终端.

. alarm时钟信号剩下的时间.

. 当前工作目录.

. 根目录.

. 文件创建掩码.

. 资源限制.

. 用户时间,系统时间,子进程用户时间,子进程系统时间.

. 记录锁.

. 进程信号掩码.

. 信号屏蔽.

. 优先级.

. 预定值.

调用成功后,系统调用修改新进程文件的最新访问时间.返回值:该系统调用一般不会有成功返回值, 因为原来的进程已荡然无存.

例子:printf("now this process will be ps command\n");

execl("/bin/ps","ps","-ef",NULL);

二、进程通讯编程

[code:1:d22bc4f5e9]1,Message queue队列编程例子

/*****************************************************************************

Excerpt from "Linux Programmer's Guide - Chapter 6"

(C)opyright 1994-1995, Scott Burkett

*****************************************************************************

MODULE: msgtool.c

*****************************************************************************

A command line tool for tinkering with SysV style Message Queues

*****************************************************************************/

#include <stdio.h>

#include <stdlib.h>

#include <ctype.h>

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/msg.h>

#define MAX_SEND_SIZE 80

struct mymsgbuf {

long mtype;

char mtext[MAX_SEND_SIZE];

};

void send_message(int qid, struct mymsgbuf *qbuf, long type, char *text);

void read_message(int qid, struct mymsgbuf *qbuf, long type);

void remove_queue(int qid);

void change_queue_mode(int qid, char *mode);

void usage(void);

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

{

key_t key;

int msgqueue_id;

struct mymsgbuf qbuf;

if(argc == 1)

usage();

/* Create unique key via call to ftok() */

/* key = ftok(".", 'w'); */

key = 123456;

printf("key=%d\n",key);

key=IPC_PRIVATE;

/* Open the queue - create if necessary */

if((tolower(argv[1][0]))!='s')

{

if((msgqueue_id = msgget(key, IPC_CREAT|0666)) == -1) {

perror("msgget");

exit(1);

}

printf("msgqueue_id=%d\n",msgqueue_id);

}

switch(tolower(argv[1][0]))

{

case 's': send_message(atoi(argv[4]), (struct mymsgbuf *)&qbuf,

atol(argv[2]), argv[3]);

break;

case 'r': read_message(msgqueue_id, &qbuf, atol(argv[2]));

break;

case 'd': remove_queue(atoi(argv[2]));

remove_queue(msgqueue_id);

break;

case 'm': change_queue_mode(msgqueue_id, argv[2]);

break;

default: usage();

}

return(0);

}

void send_message(int qid, struct mymsgbuf *qbuf, long type, char *text)

{

printf("msgqueue_id=%d\n",qid);

/* Send a message to the queue */

printf("Sending a message ...\n");

qbuf->mtype = type;

strcpy(qbuf->mtext, text);

printf(" Type: %ld Text: %s\n", qbuf->mtype, qbuf->mtext);

if((msgsnd(qid, (struct msgbuf *)qbuf,

strlen(qbuf->mtext)+1, 0)) ==-1)

{

perror("msgsnd");

exit(1);

}

}

void read_message(int qid, struct mymsgbuf *qbuf, long type)

{

/* Read a message from the queue */

printf("Reading a message ...\n");

qbuf->mtype = type;

msgrcv(qid, (struct msgbuf *)qbuf, MAX_SEND_SIZE, type, 0);

printf(" Type: %ld Text: %s\n", qbuf->mtype, qbuf->mtext);

}

void remove_queue(int qid)

{

/* Remove the queue */

msgctl(qid, IPC_RMID, 0);

}

void change_queue_mode(int qid, char *mode)

{

struct msqid_ds myqueue_ds;

/* Get current info */

msgctl(qid, IPC_STAT, &myqueue_ds);

/* Convert and load the mode */

sscanf(mode, "%ho", &myqueue_ds.msg_perm.mode);

/* Update the mode */

msgctl(qid, IPC_SET, &myqueue_ds);

}

void usage(void)

{

fprintf(stderr, "msgtool - A utility for tinkering with msg queues\n");

fprintf(stderr, "\nUSAGE: msgtool (s)end <type> <messagetext> <msgid>\n");

fprintf(stderr, " (r)ecv <type>\n");

fprintf(stderr, " (d)elete\n");

fprintf(stderr, " (m)ode <octal mode>\n");

fprintf(stderr, "note: type must be number!\n");

exit(1);

}

2,Tcp/IP socket编程例子

1), Client方

#include <stdio.h>

#include <sys/types.h>

#include <sys/socket.h>

#include <;netinet/in.h>

#include <arpa/inet.h>

#include <;netdb.h>

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

{

int sockfd ,newsockfd, help, sent;

struct sockaddr_in peer;

struct hostent *serverhost;

char buff[5000];

if(argc<2) {

fprintf(stderr, "Usage: coc <hostname>\n");

exit(1);

}

if ((sockfd = socket(AF_INET,SOCK_STREAM,0)) < 0 ) {

perror("socket");

exit(1);

}

if((serverhost = gethostbyname(argv[1])) == 0) {

perror("gethostbyname");

exit(1);

}

peer.sin_family = AF_INET;

peer.sin_port = htons(10000);

peer.sin_addr = *(struct in_addr*)serverhost->h_addr_list[0];

if (connect(sockfd, &peer, sizeof(peer)) < 0 ) {

perror("connect");

exit(1);

}

for(help=0; help<sizeof(buff); help++)

buff[help] = '0'+help%10;

write(sockfd, buff, 5000);

close(sockfd);

}

2, Server方

#include <stdio.h>

#include <sys/types.h>

#include <sys/socket.h>

#include <;netinet

[1] [2] 下一页

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有