您好,欢迎访问三七文档
当前位置:首页 > 电子/通信 > 综合/其它 > Linux进程和管道通信
linux进程和管道通信1、程序和进程1.1程序程序(program)是存放在磁盘文件中的可执行文件。1.2进程和进程ID程序的执行实例被称为进程(process)。某些操作系统用任务表示正被执行的程序。每个linux进程都一定有一个唯一的数字标识符,称为进程ID(processID)。进程ID总是一非负整数。1.3linux下的进程结构Linux系统是一个多进程的系统,进程之间具有并行性、互不干扰的特点。linux中进程包含3个段,分别为“代码段”、“数据段”和“堆栈段”。“数据段”存放全局变量、常数以及动态数据分配的空间(malloc函数取得的空间);“代码段”存放程序代码;“堆栈段”存放子程序的返回地址、子程序的参数以及程序的局部变量。代码段数据段堆栈段1.4获取进程标识#includesys/types.h#includeunistd.hpid_tgetpid(void);返回:调用进程的进程IDpid_tgetppid(void);返回:调用进程的父进程IDuid_tgetuid(void);返回:调用进程的实际用户IDuid_tgeteuid(void);返回:调用进程的有效用户IDgid_tgetgid(void);返回:调用进程的实际组IDgid_tgetegid(void);返回:调用进程的有效组ID1.5fork函数#includesys/types.h#includeunistd.hpid_tfork(void);返回:子进程中为0,父进程中为子进程ID,出错为-11.6进程创建由fork创建的新进程被称为子进程(childprocess)。该函数被调用一次,但返回两次。两次返回的区别是子进程的返回值是0,而父进程的返回值则是子进程的进程ID。一般来说,在fork之后是父进程先执行还是子进程先执行是不确定的。这取决于内核所使用的调度算法。使用fork函数得到的子进程是父进程的处继承了整个进程的地址空间,包括:进程上下文、进程堆栈、内存信息、打开的文件描述符、信号控制设置、进程优先级、进程组号、当前工作目录、根目录、资源限制、控制终端等。父、子进程之间的区别是:fork的返回值;进程ID、不同的父进程ID;子进程的tms_utime,tms_stime,tms_cutime以及tms_ustime设置为0;父进程设置的锁,子进程不继承;子进程的未决告警被清除;子进程的未决信号集设置为空集。2、进程间通信概述进程间通信有如下一些目的:数据传输:一个进程需要将它的数据发送给另一个进程,发送的数据量在一个字节到几兆字节之间。共享数据:多个进程想要操作共享数据,一个进程对共享数据的修改,别的进程应该立刻看到。通知事件:一个进程需要向另一个或一组进程发送消息,通知它(它们)发生了某种事件(如进程终止时要通知父进程)。资源共享:多个进程之间共享同样的资源。为了作到这一点,需要内核提供锁和同步机制。进程控制:有些进程希望完全控制另一个进程的执行(如Debug进程),此时控制进程希望能够拦截另一个进程的所有陷入和异常,并能够及时知道它的状态改变。现在linux使用的进程间通信方式:(1)管道(pipe)和命名管道(FIFO)(2)信号(signal)(3)消息队列(4)共享内存(5)信号量(6)套接字(socket)2.1管道创建与关闭创建一个简单的管道,可以使用系统调用pipe()。它接受一个参数,也就是一个包括两个整数的数组。如果系统调用成功,此数组将包括管道使用的两个文件描述符。创建一个管道之后,一般情况下进程将产生一个新的进程。系统调用:pipe();原型:intpipe(intfd[2]);返回值:如果系统调用成功,返回0。如果系统调用失败返回-1:errno=EMFILE(没有空闲的文件描述符)ENFILE(系统文件表已满)EFAULT(fd数组无效)注意:fd[0]用于读取管道,fd[1]用于写入管道。图1linux中管道与文件描述符的关系2.2管道读写管道主要用于不同进程间通信。实际上,通常先创建一个管道,再通过fork函数创建一个子进程。图2父子进程管道的文件描述符对应关系子进程写入和父进程读的命名管道:图3关闭父进程fd[1]和子进程[0]2.3管道读写注意事项可以通过打开两个管道来创建一个双向的管道。但需要在子进程中正确地设置文件描述符。必须在系统调用fork()中调用pipe(),否则子进程将不会继承文件描述符。当使用半双工管道时,任何关联的进程都必须共享一个相关的祖先进程。因为管道存在于系统内核之中,所以任何不在创建管道的进程的祖先进程之中的进程都将无法寻址它。而在命名管道中却不是这样。3.消息队列(消息通信)消息队列就是消息的一个链表,它允许一个或多个进程向它写消息,一个或多个进程从中读消息。具有一定的FIFO的特性,但是可实现消息的随即查询。这些消息存在于内核中,由“队列ID”来标识。消息队列的实现包括创建和打开队列、添加消息、读取消息和控制消息队列这四种操作。msgget:创建和打开队列,其消息数量受系统限制。msgsnd:添加消息,将消息添加到消息队列尾部。msgrcv:读取消息,从消息队列中取走消息。msgctl:控制消息队列。intmsgget(key_tkey,intflag)key:返回新的或已有队列的ID,msgflg:消息队列的建立标志和存取权限。intmsgsnd(intmsqid,structmsgbuf*msgp,size_tmsgsz,intmsgflg)其中:msqid是消息队列的队列ID;◦msgp是消息内容所在的缓冲区;◦msgsz是消息的大小;◦msgflg是标志,IPC_NOWAIT若消息并没有立即发送而调用进程会立即返回。structmsgbuf{longmtype;/*typeofmessage*/charmtext[1];/*messagetext*/};intmsgrcv(intmsqid,structmsgbuf*msgp,size_tmsgsz,longmsgtyp,intmsgflag)◦msqid是消息队列的引用标识符;◦msgp是接收到的消息将要存放的缓冲区;◦msgsz是消息的大小;◦msgtyp是期望接收的消息类型;◦msgflg是标志。intmsgctl(intmsqid,intcmd,structmsqid_ds*buf)msqid是消息队列的引用标识符;cmd是执行命令;buf是一个缓冲区。cmd参数指定对于由msqid规定的队列要执行的命令:◦IPC_STAT取此队列的msqid_ds结构,并将其存放在buf指向的结构中。◦IPC_SET按由buf指向的结构中的值,设置与此队列相关的结构中的下列四个字段:msg_perm.uid、msg_perm.gid、msg_perm;mode和msg_qbytes。此命令只能由下列两种进程执行:一种是其有效用户ID等于msg_perm.cuid或msg_perm.uid;另一种是具有超级用户特权的进程。只有超级用户才能增加msg_qbytes的值。◦IPC_RMID从系统中删除该消息队列以及仍在该队列上的所有数据。这种删除立即生效。仍在使用这一消息队列的其他进程在它们下一次试图对此队列进行操作时,将出错返回EIDRM。此命令只能由下列两种进程执行:一种是其有效用户ID等于msg_perm.cuid或msg_perm.uid;另一种是具有超级用户特权的进程。
本文标题:Linux进程和管道通信
链接地址:https://www.777doc.com/doc-3138742 .html