linux进程创建和通信.ppt_第1页
linux进程创建和通信.ppt_第2页
linux进程创建和通信.ppt_第3页
linux进程创建和通信.ppt_第4页
linux进程创建和通信.ppt_第5页
已阅读5页,还剩62页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、 Linux 进程控制及进程间通信 Email:SummaryLinux进程创建、撤销Linux进程间的通信Linux进程创建、撤销Linux进程控制包括的内容:进程创建、进程撤销进程睡眠、进程唤醒Linux进程创建、撤销Linux进程的族亲关系Linux进程之间不是孤立存在的,它们之间有一定的族亲关系。进程1进程2父进程子进程产 生Linux进程创建子进程1与子进程2构成兄弟进程。(按照创建时间确定,先者为兄,后者为弟); 父进程子进程1子进程2Linux进程创建Linux系统的进程树init进程A进程B进程C进程D进程E进程F系统加电启动后,系统中只有一个进程初始化进程,又称init进程(

2、对应的结构体init_task)。Init进程是所有进程的祖先进程,它的进程pid=1Linux进程创建Linux进程的创建在linux中除了init进程是由系统启动时创建的外,其他所有进程都是由当前进程使用系统调用fork()创建的。进程创建后父子进程在系统中并发执行。Linux进程创建的重要特点:Linux对子进程继承父进程的虚拟存储空间有独特的处理方法:它把所谓的继承当作共享来处理 。所谓共享指子进程在创建时并不建立虚拟内存空间,而是子进程与父进程共享父进程的虚拟内存空间。即:子进程在创建后共享父进程的虚存空间,所以子进程在刚创建时使用的是父进程的代码段、数据段。即子进程在创建后执行的时

3、父进程的程序代码。Linux进程创建”写时拷贝“技术子进程在何时如何建立自己的虚拟内存空间?只有在两个进程中某个进程要向虚拟内存写入时,才建立子进程自己的虚拟内存空间,并把原来虚拟内存空间的内容拷贝到新建立的虚拟内存区域中,然后在新建的虚拟内存空间写入信息.Linux进程创建Fork()系统调用父进程创建子进程是通过 fork()系统调用完成的。此时一个进程“分裂”成两个进程:一个是原来的进程,一个是新创建的进程。通过fork()返回值区分父子进程:对父进程而言,返回的是子进程的PID对子进程而言,返回的是0Linux进程创建在语句val=fork()之前,只有一个进程在执行这段代码,但在这条

4、语句之后,就变成两个进程在执行了,这两个进程的代码部分完全相同。两个进程中,原先就存在的那个被称作“父进程”,新出现的那个被称作“子进程”。父子进程的区别除了进程标志符(process ID)不同外,变量pid的值也不相同,pid存放的是fork的返回值。fork调用的一个奇妙之处就是它仅仅被调用一次,却能够返回两次,它可能有三种不同的返回值:在父进程中,fork返回新创建子进程的进程ID;在子进程中,fork返回0;如果出现错误,fork返回一个负值;Linux进程创建举例:#include#includemain() pid_t val; printf(PID before fork():

5、%dn,(int)getpid(); if(val=fork()printf(parent process PID:%dn,(int)getpid(); elseprintf(child process PID:%dn,(int)getpid();执行结果PID before fork():490parent process PID:490child process PID:491Linux子进程的执行子进程的执行创建进程的目的是需要该进程完成一定的任务,执行它的程序代码。Linux中,使程序执行的唯一方法是使用系统调用exec()Exec()函数族#include int execl(con

6、st char *path, const char *arg, .);int execlp(const char *file, const char *arg, .); int execle(const char *path, const char *arg, ., char *const envp);int execv(const char *path, char *const argv); int execvp(const char *file, char *const argv);int execve(const char *path, char *const argv, char *c

7、onst envp); Linux进程创建int execl(const char *path, const char *arg, .);Path指出了要执行的程序的完整路径Arg0表示要执行的文件名或命令名Arg1.argn表示可执行文件或命令需要的参数#includevoid main() if(fork() printf(“this is the parent process!n”); else execl(“/bin/ls”,”ls”,”-l”,0); return;举例:Linux进程终止和撤销Linux进程终止exit()终止的两种情况:正常终止 :完成本身任务而终止,调用exit

8、()或运行到最后而终止被内核强制终止:运行中出现了致命错误。终止的进程占有部分系统资源,必须撤销它们exit()往往会带有参数,如exit(0)表示正常退出,非零表示不正常退出。终止的进程状态为TASK_ZOMBIE系统调用exit,它的作用是使进程退出,但也仅仅限于将一个正常的进程变成一个僵尸进程,并不能将其完全销毁僵尸进程中保存着很多对程序员和系统管理员非常重要的信息,首先,这个进程是怎么死亡的?是正常退出呢,还是出现了错误,还是被其它进程强迫退出的?其次,这个进程占用的总系统CPU时间和总用户CPU时间分别是多少?发生页错误的数目和收到信号的数目。这些信息都被存储在僵尸进程中,Linux

9、进程终止和撤销进程的撤销release()一个进程终止后不能自己撤销自己,而只能由他的父进程或祖先进程撤销它。父进程建立子进程后,使用wait()系统调用等待子进程终止,当检查到子进程的状态是僵死态时,撤销子进程,调用release()函数,释放僵死进程的描述符如果父进程早子进程终止,为了使子进程不成为孤立进程,内核将这些子进程赋予init进程,使init进程成为它们的父进程,它们的撤销也由init进程完成。wait的函数原型是:#include #include pid_t wait(int *status) 进程一旦调用了wait,就立即阻塞自己,由wait自动分析是否当前进程的某个子进程

10、已经退出,如果让它找到了这样一个已经变成僵尸的子进程,wait就会收集这个子进程的信息,并把它彻底销毁后返回;如果没有找到这样一个子进程,wait就会一直阻塞在这里,直到有一个出现为止。参数status用来保存被收集进程退出时的一些状态,它是一个指向int类型的指针。如果成功,wait会返回被收集的子进程的进程IDwaitpid:pid_t waitpid(pid_t pid,int *status,int options)系统调用waitpid和wait的作用是完全相同的,但waitpid多出了两个可由用户控制的参数pid和options,从而为我们编程提供了另一种更灵活的方式 。当pid取

11、不同的值时,在这里有不同的意义。1.pid0时,只等待进程ID等于pid的子进程,不管其它已经有多少子进程运行结束退出了,只要指定的子进程还没有结束,waitpid就会一直等下去。2.pid=-1时,等待任何一个子进程退出,没有任何限制,此时waitpid和wait的作用一模一样。3.pid=0时,等待同一个进程组中的任何子进程,如果子进程已经加入了别的进程组,waitpid不会对它做任何理睬。4.pid-1时,等待一个指定进程组中的任何子进程,这个进程组的ID等于pid的绝对值。options参数目前在Linux中只支持WNOHANG和WUNTRACED两个选项如果我们不想使用它们,也可以把

12、options设为0进程通信进程通信:进程间信息交换。低级通信机制:信息量小,如pv操作。高级通信机制:信息量大。高级通信方式:消息通信机制(直接通信、信箱通信)共享内存管道信号Linux进程间通信在Linux系统中,以进程为单位分配和管理资源。由于保护的缘故,一个进程不能直接访问另一个进程的资源,也就是说,进程之间互相封闭 信号:信号每次只能传递一个数据; linux管道:管道只能在两个进程间单向交换信息 ;IPC(Internal Process Communication)消息队列 IPC共享内存IPC信号量机制Linux进程间通信管道机制管道机制 管道是Linux的一种最简单的通信机制

13、。管道的概念: 管道机制是一个数据的逻辑“通道” 。管道写进程读进程Linux把管道当作是一种文件,采用文件管理的办法管理管道。管道与文件的区别在于 ,管道不使用外存,而是使用内存存放传送的数据Linux进程间通信管道机制管道特点 传送方向固定的单向管道,一个管道的数据只能向一个方向传送,并且管道一旦确定了其数据传送方向后就不能再更改。数据在管道中以字符流的形态传送的,即以字节为单位的顺序数据(FIFO方式)管道分类有名管道无名管道区别无名管道只能在父子进程之间通信,有名管道可以在任意进程间通信无名管道没有名字标识,有名管道有名称。Linux进程间通信管道机制无名管道:无名管道的系统调用:#i

14、nclude int pipe(int pipe2)参数是2个元素的int型数组,pipe0是读取管道的文件标识符,pipe1是写入管道的文件标识符Linux进程间通信管道机制用法: 用于亲缘关系的进程间的通信,主要用于父子进程间的通信。*先建立管道再建立子进程的顺序若不然,先建立子进程,再建立管道,管道只对建立它的进程可见,对另一个进程是看不见的,因此无法实现父子间的通信。确定管道通信的方向(单向通信)管道Pipe1Pipe0Linux进程间通信管道机制举例:在该例中,父进程建立管道后创建一个子进程。子进程的任务是把一组字符串信息写入管道,父进程在子进程完成任务终止后,从管道中读取信息并显示

15、在显示器上。 Linux进程间通信管道机制有名管道 无名管道只能在父子进程间通信,为了解决这个问题,linux提供了有名管道。有名管道的系统调用#include Int mkfifo(const char *path,mode_t mode)参数说明:Path:要使用的命名管道的路径和名字Mode指明管道的访问权限返回值:成功返回值0;否则返回负数;Linux进程间通信管道机制举例例:有两个程序,其中一个程序把一组信息写入管道,另一个程序把管道中的信息读出后显示在屏幕上。uLinux进程间通信IPC共享内存共向内存是进程间通信速度最快的一种。思想:允许多个进程访问同一个内存区域实行进程之间的数

16、据传送多任务操作系统不允许用户进程直接访问物理内存,即物理内存对用户进程不可见。每个进程只能看见自己的虚拟内存空间Linux采用内存映射技术把共享内存区域映射到有关进程的虚拟内存空间,使他成为进程虚拟内存的一部分,从而进程可以对这部分虚拟内存区域进行读写。进程与共享内存的结合;共享内存映射到进程虚拟区域的过程进程与虚拟内存的分离;当使用共享内存完成数据交换后需要释放相关的虚拟内存区域,即脱离与共享内存的的联系。Linux进程间通信IPC共享内存共享内存区域进程A进程B0 x50000 x30000 x70000 x5000Linux进程间通信IPC共享内存共享内存使用标识号来标识:共享内存标识

17、号shmid每个共享内存区域由一个数据结构记录管理信息,称为共享内存描述符,称为结构体shmid_ds.Struct shmid_dsStruct ipc_perm shm_perm; /*访问权限*/Int shm_segsz;/*共享内存大小(字节)*/Time_t shm_atime;/*最近一次结合时间*/Time_t shm_dtime;/*最近一次分离时间*/Time_t shm_ctime;/*最近一次修改时间*/Unsigned short shm_cpid;/*创建者pid*/Unsigned short shm_lpid;/*最后一次对共享内存进行操作的进程的pid*/Sh

18、ort shm_nattch;/*当前结合进程的数量*/Unsigned short shm_npages;/*共享内存使用的页面数*/Unsigned long shm_pages;/*共享内存页表指针*/Struct vm_area_struct *attaches;/*供结合进程使用的虚拟内存描述符*/Linux进程间通信IPC共享内存Linux进程间通信IPC共享内存共享内存的生成与控制共享内存的创建shmflg与消息队列的flag一样函数返回共享内存标识符shmidInt shmget(key_t key,int size,int shmflg)Linux进程间通信IPC对象管理的一

19、个重要特点是,系统使用一个键值和一个标识号来识别每个IPC对象。键值和标识号是唯一的,而且是一一对应的标识号是进程运行过程中动态产生的,进程之间相互独立,那么该标识号对其它进程不可见。无法完成进程间的通信。Key作为一个静态的识别值,它独立于所有进程,但对所有进程可见。为什么使用两种标识方法:KeyLinux进程间通信Key键值的生成:使用一个文件名和一个符号调用C函数ftok()生成。Pathname:一个已经存在的路径和文件名proj是任意一个符号Ket_t ftok(char *pathname,char proj)公有键值:ftok()生成的键值或用户自己指定的键值私有键值:IPC_P

20、RIVATE,它是私有的,仅在进程及子进程中可见。Linux进程间通信Msgflg参数 指定消息队列的访问权限和操作模式0400 允许创建者读0200 允许创建者写0040 允许创建者同组用户读0020 允许创建者同组用户写0004 允许其它进程读0002 允许其它进程写Linux进程间通信IPC共享内存共享内存的控制Cmd:IPC_STAT;获取共享内存的管理信息,把该共享内存的描述符内容复制到buf指向的结构体IPC_SET:修改共享内存描述符内容IPC_RMID:删除共享内存Shmctl(int shmid,int cmd,struct shmid_ds *buf)Linux进程间通信I

21、PC共享内存与共享内存的结合Shmaddr:进程指定的共享内存在进程虚存空间的起始地址,若参数为0,则由系统自动分配Shmflg为SHM_RDONLY时只能对共享内存进行读取操作,而不能写入。为0时,可以读取写入。Int shmat(int shmid,char*shmaddr,int shmflg)Linux进程间通信IPC共享内存与共享内存的分离Int shmdt(char*shmaddr)Shmaddr:进出虚拟空间中共享内存的首地址。执行该函数将释放进程虚拟空间中共享内存占用的区域,并修改shmid_ds中的相关项。 Linux进程间通信IPC共享内存举例:#define KEY 12

22、34 /* 键 */#define SIZE 1024 /* 欲建立的共享内存的大小 */int main()int shmid;char *shmaddr;struct shmid_ds buf;shmid = shmget(KEY,SIZE,IPC_CREAT|0600); /* 建立共享内存 */if(shmid = -1)printf(create share memory failed: %s,strerror(errno);return 0;if(fork() = 0) /* 子进程 */* 系统自动选择一个地址连接 */shmaddr = (char *)shmat(shmid,

23、NULL,0);if(shmaddr = (void *)-1)printf(connect to the share memory failed: %s,strerror(errno);return 0;strcpy(shmaddr,hello, this is child process!n);shmdt(shmaddr); /* detach共享内存 */return 0;else /* 父进程 */sleep(3); /* 等待子进程执行完毕 */shmctl(shmid,IPC_STAT,&buf); /* 取得共享内存的相关信息 */printf( size of the shar

24、e memory: );printf(shm_segsz = %d bytes n,buf.shm_segsz);printf( process id of the creator: );printf(shm_cpid = %d n,buf.shm_cpid);printf( process id of the last operator: );printf(shm_lpid = %d n,buf.shm_lpid);/* 系统自动选择一个地址连接 */shmaddr = (char *)shmat(shmid,NULL,0);if(shmaddr = (void *)-1)printf(co

25、nnect the share memory failed: %s,strerror(errno);return 0;printf(print the content of the share memory: );printf(%s n,shmaddr);shmdt(shmaddr); /* detach共享内存 */* 当不再有任何其它进程使用该共享内存时系统将自动销毁它 */shmctl(shmid,IPC_RMID,NULL);wait(null); Linux信号量机制Linux的信号量机制有两种:其本身设置的信号量机制引进UNIX SYSTEM V的IPC中的信号量机制。它更完善、更

26、方便使用。它可以一次性地对多个信号量进行PV操作。 本节介绍后者,其涉及到的函数和数据结构分别定义在Linux源文件的ipc/sem.c和include/linux/sem.hIPC信号量机制信号量系统中每个信号量对应一个信号量结构体sem,其定义如下:Struct semShort semval; /*信号量的值*/Unshort sempid; /*记录对信号量最后一次实施操作进程的PID*/(为了解决死锁)IPC信号量机制在这方面做了改进,它可以使用原语一次对多个信号量进行操作。为此,引进了信号量集合的概念:把进程需要访问资源对应的信号量组成一个信号量集合。IPC信号量机制信号量集合 信

27、号量数组:在IPC信号量机制中把多个信号量组成一个信号量集合,该集合由信号量结构体sem组成,称为信号量数组。 信号量集合描述符系统中的每个信号量集合用一个描述符描述其特征和记载其管理信息 。Struct semid_dsStruct_ipc_perm sem_perm;/*对信号量集合的访问权限*/Time_t sem_otime;/*最后操作信号量集的时间*/Time_t sem_ctime;/*最后修改信号量集的时间*/Struct sem *sem_base;/*指向信号量数组*/Struct sem_queue *sem_pending;/*指向等待队列头*/Struct sem_q

28、ueue *sem_pending_last;/* 指向等待队列尾*/Struct sem_undo *undo;/*/Unshort sem_nsems;/*信号量集合中信号量的数目*/IPC信号量机制IPC对系统中的所有信号量集合进行集中管理,把所有的信号量集合描述符组织在一个semary数组中,其定义如下:Static struct semid_ds *smearySEMMNI;其中SEMMNI是系统中可以设置的信号量集合的最大数目 IPC信号量机制信号量集合的创建Int semget(key_t key, int nsems, int semflg)参数说明:Key:要创建或要获取的信

29、号量集合的标志键值(与前同) 。Nsems:指出要创建的信号量集合中包含的信号量的个数。Semflgs:操作标志;指定了信号量集合的访问权限和操作模式(与前同)。 返回值:该系统调用正常则返回值为信号量集合的标识号,出错则返回负数。IPC信号量机制信号量PV操作IPC中没有对信号量分别设置P和V操作原语,而是统一由具有原语性质的系统调用semop()实现的,通常称其为信号量操作函数。其定义如下:Int semop(int semid,struct sembuf *sops, unsigned nsops); 参数说明:Semid:实施pv操作的信号量集合的标识号Nsops:本次实施操作的信号量

30、的个数Sops:指向一个信号量操作数组。因为每次对信号量集合中实施操作的信号量个数不同,不同信号量实施的操作不同,所以必须指明本次操作是对哪些信号量,实施哪些操作。该数组的元素个数就是Nsops。IPC信号量机制Sops中的每个元素是一个sembuf结构体:Struct sembufUshort sem_num; /*指出信号量在信号量数组中的下标*/Short sem_op;/*指出操作的种类*/Short sem_flg;/*指出操作的标志: 通常取值0;若为IPC_NOWAIT,则即使出现需要进程阻塞的情况,也不阻塞,而是继续运行。*/Sem_op的值决定操作的类型:0:表示进程释放资源,则实施V操作,把semval的值加上sem_op以上两种情况下:若对信号量集实施操作后,所有信号量的值semval均0,则函数返回0,表示进程所需的多个资源都可用,此时进程可以继续运行;否则,只要有一个semval0,则表示进程需要的这种资源不可用,进程阻塞。=0。此时若semval也是0,则函数返回,调用semop的进程继续执行;若semval非0,则进程被阻塞。IPC信号量机制信号量操作等待队列 进程执行信号

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论