LINUX环境编程-进程编程.ppt
《LINUX环境编程-进程编程.ppt》由会员分享,可在线阅读,更多相关《LINUX环境编程-进程编程.ppt(35页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、LINUX应用编程 进程篇20092009年年1212月月2222日日LINUXLINUX应用编程应用编程-进程篇进程篇HTTPHTTP协议协议HTMLHTML语言语言CGICGI编程编程2进程编程进程编程 进程与程序进程与程序uu程序是一个包含可执行代码的文件,它放在磁盘等介质上。程序是一个包含可执行代码的文件,它放在磁盘等介质上。uu当程序被操作系统装载到内存并分配给它一定资源后,此当程序被操作系统装载到内存并分配给它一定资源后,此时可称为进程。时可称为进程。uu为方便操作系统管理,每个进程都会有一个唯一的非负整为方便操作系统管理,每个进程都会有一个唯一的非负整数编号。数编号。uu程序是一
2、个静态概念,进程是一个动态概念。程序是一个静态概念,进程是一个动态概念。3进程编程进程编程 内存空间内存空间LinuxLinux的虚拟地址空间也为的虚拟地址空间也为0 04G4G,LinuxLinux将整个将整个4G4G线性地址空间分为用户线性地址空间分为用户空间和内核空间两部分,空间和内核空间两部分,最高的最高的1G1G字节字节(从虚拟地址(从虚拟地址0 xC00000000 xC0000000到到0 xFFFFFFFF0 xFFFFFFFF),供内核使用,称为),供内核使用,称为“内内核空间核空间”。而将较低的而将较低的3G3G字节(从虚拟字节(从虚拟地址地址0 x000000000 x0
3、0000000到到0 xBFFFFFFF0 xBFFFFFFF),供),供各个进程使用,称为各个进程使用,称为“用户空间)。因用户空间)。因为每个进程可以通过系统调用进入内核,为每个进程可以通过系统调用进入内核,因此,因此,LinuxLinux内核由系统内的所有进程共内核由系统内的所有进程共享。享。于是,从具体进程的角度来看,每于是,从具体进程的角度来看,每个进程可以拥有个进程可以拥有4G4G字节的虚拟空间。字节的虚拟空间。当进程陷入内核时,内核代表进程运行。当进程陷入内核时,内核代表进程运行。4进程编程进程编程 进程描述进程描述pp进程描述符:当进程产生时有进程描述符:当进程产生时有Linu
4、xLinux操作系统分配。操作系统分配。pp内存:用来存放进程要执行的代码和使用的数据。内存:用来存放进程要执行的代码和使用的数据。pp文件描述符:进程运行时打开的文件。文件描述符:进程运行时打开的文件。pp认证信息:用户和组认证信息:用户和组IDIDpp进程执行环境:各种环境变量进程执行环境:各种环境变量pp资源安排:资源安排:CPUCPU时间时间pp进程状态进程状态5进程编程进程编程 进程状态进程状态pp用户状态:进程在用户状态下运行的状态。用户状态:进程在用户状态下运行的状态。pp内核状态:进程在内核状态下运行的状态。内核状态:进程在内核状态下运行的状态。pp内存中就绪:进程没有执行,但
5、处于就绪状态,只要内核调度它,就可以执内存中就绪:进程没有执行,但处于就绪状态,只要内核调度它,就可以执行。行。pp内存中睡眠:进程正在睡眠并且进程存储在内存中,没有被交换到内存中睡眠:进程正在睡眠并且进程存储在内存中,没有被交换到SWAPSWAP设备。设备。pp就绪且换出:进程处于就绪状态,但是必须把它换入内存,内核才能再次调就绪且换出:进程处于就绪状态,但是必须把它换入内存,内核才能再次调度它进行运行。度它进行运行。pp睡眠且换出:进程正在睡眠,且被换出内存。睡眠且换出:进程正在睡眠,且被换出内存。pp被抢先:进程从内核状态返回用户状态时,内核抢先于它,做了上下文切换,被抢先:进程从内核状
6、态返回用户状态时,内核抢先于它,做了上下文切换,调度了另一个进程。原先这个进程就处于被抢先状态。调度了另一个进程。原先这个进程就处于被抢先状态。pp创建状态:进程刚被创建。该进程存在,但既不是就绪状态,也不是睡眠状创建状态:进程刚被创建。该进程存在,但既不是就绪状态,也不是睡眠状态。这个状态是除了进程态。这个状态是除了进程0 0以外的所有进程的最初状态。以外的所有进程的最初状态。pp僵死状态(僵死状态(zombiezombie):进程调用):进程调用exitexit结束,进程不再存在,但在进程表项中仍结束,进程不再存在,但在进程表项中仍有纪录,该纪录可由父进程收集。有纪录,该纪录可由父进程收集
7、。6进程编程进程编程 进程状态及转换进程状态及转换图如下:图如下:7进程调度原理图进程调度原理图8进程编程进程编程 进程的布局进程的布局pp栈用来存放栈用来存放局部变量局部变量和和函数的返函数的返回地址回地址。地址从高到低生长。地址从高到低生长。pp堆是一块堆是一块连续连续的内存,有低地址的内存,有低地址向高地址生长。需要程序在运行向高地址生长。需要程序在运行时时动态动态申请和释放。申请和释放。pp数据段存放了程序运行时的各种数据段存放了程序运行时的各种数据。数据。pp代码段存放了可执行指令,一般代码段存放了可执行指令,一般为只读。为只读。9进程编程进程编程 进程的环境变量进程的环境变量pp环
8、境变量和命令行参数都环境变量和命令行参数都放在进程的高地址。放在进程的高地址。pp环境变量可用环境变量可用 environenviron来引来引用。以用。以name=stringname=string的形式存的形式存放。放。#include#include#include extern char*environ;int main(int argc,char*argv)int i=0;for(i=0;environi;i+)printf(%sn,environi);return 0;10进程编程进程编程 EXIT EXIT系统调用系统调用系统调用系统调用exitexit的功能是终止发出调用的进程
9、。它的声明格式如下:的功能是终止发出调用的进程。它的声明格式如下:#include#include void void exit(intexit(int status);status);#include#include void _ void _exit(intexit(int status);status);系统调用系统调用_exit_exit立即终止发出调用的进程。所有属于该进程的文件描述符都关立即终止发出调用的进程。所有属于该进程的文件描述符都关闭。该进程的所有子进程由进程闭。该进程的所有子进程由进程1 1(进程(进程initinit)接收,并对该进程的父进程发)接收,并对该进程的父进程
10、发 出出一个一个SIGCHLDSIGCHLD(子进程僵死)的信号。参数(子进程僵死)的信号。参数statusstatus作为退出的状态值返回父进程,作为退出的状态值返回父进程,该值可以通过系统调用该值可以通过系统调用waitwait来收集。返回状态码来收集。返回状态码status status 只有最低一个字节有效。只有最低一个字节有效。如果进程是一个控制终端进程,则如果进程是一个控制终端进程,则SIGHUPSIGHUP信号将被送往该控制终端的前台进程。信号将被送往该控制终端的前台进程。系统调用系统调用_exit_exit从不返回任何值给发出调用的进从不返回任何值给发出调用的进 程;也不刷新程
11、;也不刷新I/OI/O缓冲,如果要自缓冲,如果要自动完成刷新,可以用函数调用动完成刷新,可以用函数调用exitexit。exitexit为为glibcglibc库函数,它会先库函数,它会先运行注册函数运行注册函数,也有可能会进行,也有可能会进行文件流的关闭操作文件流的关闭操作,之后再调用之后再调用_exit_exit系统调用。系统调用。11进程编程进程编程 RETURN RETURN退出进程退出进程ppreturnreturn的返回值就是进程终止时的返回状态。的返回值就是进程终止时的返回状态。pp如果如果returnreturn没有返回任何值,进程的返回状态是什么?没有返回任何值,进程的返回状
12、态是什么?pp在在 gccgcc加加std=c99std=c99编译选项下,进程返回状态又是什么?编译选项下,进程返回状态又是什么?ppC99C99:是:是ISOISO组织在组织在9999年新制定的年新制定的c c标准,使标准,使C C更可靠。更可靠。pp分别用分别用 gccgcc main.cmain.c 和和gccgcc main.cmain.c std=c99 std=c99编译,观察返回值。编译,观察返回值。12进程编程进程编程 进程终止处理函数进程终止处理函数A Atexittexit()()函数用于注册一个进程正常终止时要调用的函数,一个进程最多可注册函数用于注册一个进程正常终止时
13、要调用的函数,一个进程最多可注册3232个终止处理函数。个终止处理函数。#include#include intint atexit(voidatexit(void(*(*function)(voidfunction)(void););成功返回成功返回0 0,失败返回非,失败返回非0 0。参数为函数指针,参数为函数指针,此函数会在进程调用此函数会在进程调用exitexit时调用时调用。在在mainmain函数返回出,分别用函数返回出,分别用returnreturn、exit(0)_exit(0),exit(0)_exit(0),看其中的区别。看其中的区别。_exit_exit函数是函数是不会调
14、用注册函数的。不会调用注册函数的。void void exit_handler(voidexit_handler(void)printf(Imprintf(Im in exit handlern);in exit handlern);intint main(intmain(int argcargc,char*,char*argvargv)if(0!=if(0!=atexit(exit_handleratexit(exit_handler)printf(registerprintf(register exit function handler failed!n);exit function ha
15、ndler failed!n);return-1;return-1;printf(beforeprintf(before exitn);exitn);exit(0);exit(0);/_exit(0);return 0;/_exit(0);return 0;13进程编程进程编程 getenv getenv、setenvsetenv函数函数ppgetenvgetenv用来获取指定环境变量。用来获取指定环境变量。#include#include char*char*getenv(constgetenv(const char*name);char*name);参数参数namename为环境变量的名称
16、,如为环境变量的名称,如 PATHPATH,SHELL SHELL 等。等。如果环境变量存在那么返回该环境变量的值,否则为如果环境变量存在那么返回该环境变量的值,否则为NULLNULLsetenvsetenv用来设置环境变量,会把用来设置环境变量,会把valuevalue拷贝到环境变量所在的内存区域。拷贝到环境变量所在的内存区域。#include#include pp intint setenv(constsetenv(const char*name,const char*value,char*name,const char*value,intint overwrite);overwrite)
17、;参数参数namename为环境变量的名称,为环境变量的名称,valuevalue为该环境变量的值。如果环境变量已经存在,为该环境变量的值。如果环境变量已经存在,overwriteoverwrite非非0 0时,改变该环境变量的值。时,改变该环境变量的值。overwriteoverwrite为为0 0时,什么都不做直接返回。时,什么都不做直接返回。成功返回成功返回0 0,失败返回,失败返回-1-1(一般为放置环境变量的内存空间不够)。(一般为放置环境变量的内存空间不够)。环境变量都是以环境变量都是以 name=stringname=string的形式存放。的形式存放。14进程编程进程编程 pu
18、tenv putenv、clearenvclearenv函数函数ppputenv putenv 无论环境变量是否存在,都会使设置值生效。无论环境变量是否存在,都会使设置值生效。#include#include intint putenv(charputenv(char*string);*string);参数参数stringstring的格式为的格式为 name=stringname=string成功返回成功返回0 0,失败返回非,失败返回非0 0putenvputenv()()函数并不拷贝环境变量字符串到进程环境表,只是存放环境变量数值的函数并不拷贝环境变量字符串到进程环境表,只是存放环境变量
19、数值的指针,而指针,而setenvsetenv()()函数则完全拷贝环境变量字符串到进程环境表。函数则完全拷贝环境变量字符串到进程环境表。分别用分别用 gccgcc putenv.cputenv.c 和和gccgcc putenv.cputenv.c DLOCAL g DLOCAL g编译,产看运行结果。把编译,产看运行结果。把putenv.cputenv.c中的中的putenvputenv换成换成setenvsetenv看结果。看结果。ppclearenvclearenv清除所有的环境变量清除所有的环境变量,并且把并且把environenviron设置为设置为NULLNULL。ppunset
20、envunsetenv清除名字为清除名字为namename的环境变量。的环境变量。#include#include intint clearenv(voidclearenv(void););intint unsetenv(constunsetenv(const char*name);char*name);15进程编程进程编程 跨函数跳转跨函数跳转ppgotogoto只能在函数中跳转,如果只能在函数中跳转,如果要求从一个函数跳到另外一个函要求从一个函数跳到另外一个函数?用数?用setjmpsetjmp和和longjmplongjmp。pp跨函数的跳转主要用在调用函跨函数的跳转主要用在调用函数层次
21、较深时,为了节约函数的数层次较深时,为了节约函数的返回时间。返回时间。如右假设我们从如右假设我们从a a函数调用到了函数调用到了z z函数。函数。a函数b函数r函数z函数16进程编程进程编程 setjmp setjmp、longjmplongjmp函数函数ppsetjmpsetjmp用来设置返回点,保存当前的寄存器值。用来设置返回点,保存当前的寄存器值。#include#include intint setjmp(jmp_bufsetjmp(jmp_buf envenv););void void longjmp(jmp_buflongjmp(jmp_buf envenv,intint valv
22、al););参数参数jmp_bufjmp_buf envenv用来保存当前寄存器值。用来保存当前寄存器值。longjmplongjmp会根据会根据envenv跳转到跳转到setjmpsetjmp处。处。一个一个setjmpsetjmp可以对应可以对应n n个个longjmplongjmp,可以用,可以用setjmpsetjmp的返回值来区分。的返回值来区分。如果成功如果成功setjmpsetjmp返回返回0 0,如果是从,如果是从longjmplongjmp返回的,那么返回值有返回的,那么返回值有longjmplongjmp的第二的第二个参数决定。所以个参数决定。所以longjmplongjm
23、p的第二个参数不可以为的第二个参数不可以为0 0,否则无法判断,否则无法判断setjmpsetjmp是如何是如何返回的。返回的。longjmplongjmp的第一个参数是的第一个参数是setjmpsetjmp返回的,第二个参数是给返回的,第二个参数是给setjmpsetjmp的返回值。的返回值。当当longjmplongjmp返回后,返回后,setjmpsetjmp所在函数中的自动变量恢复到调用所在函数中的自动变量恢复到调用setjmpsetjmp时的值。如果时的值。如果变量是保存在内存中的,那么它的值仍然是调用变量是保存在内存中的,那么它的值仍然是调用longjmplongjmp的时候的值。
24、的时候的值。当你希望变量值在当你希望变量值在setjmpsetjmp和和longjmplongjmp时仍然保持其值,但必须用时仍然保持其值,但必须用volatilevolatile说明该变说明该变量,并且需打开量,并且需打开-O-O优化选项。优化选项。gccgcc setjmp.csetjmp.c 和和 gccgcc setjmp.csetjmp.c O O观察运行结果。观察运行结果。17进程编程进程编程 getpid getpid、getppidgetppid函数函数ppgetpidgetpid得到自己的进程得到自己的进程IDID,getppidgetppid得到自己父进程得到自己父进程ID
25、ID#include sys/#include#include#include pid_tpid_t getpid(voidgetpid(void););pid_tpid_t getppid(voidgetppid(void););返回值为进程返回值为进程IDID,进程,进程IDID一般为一非负整数值。一般为一非负整数值。18进程编程进程编程 fork fork:进程的创建:进程的创建pp我们可以在我们可以在shellshell里敲入命令的方式来创建进程,也可以在在程序中通过调用里敲入命令的方式来创建进程,也可以在在程序中通过调用forkfork系统调用来生成新的进程系统调用来生成新的进程 。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- LINUX 环境 编程 进程
限制150内