收藏 分销(赏)

Linux系统编程介绍.ppt

上传人:xrp****65 文档编号:14026200 上传时间:2026-06-09 格式:PPT 页数:172 大小:1.21MB 下载积分:10 金币
下载 相关
Linux系统编程介绍.ppt_第1页
第1页 / 共172页
Linux系统编程介绍.ppt_第2页
第2页 / 共172页


点击查看更多>>
资源描述
单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,*,Linux,系统编程介绍,第三章,1,本章目标,系统编程与应用编程,系统资源,系统调用,系统调用与,C,库关系,错误处理,2,系统编程与应用编程,系统编程,在操作系统之上利用系统调用、,C,库进行对系统资源进行访问。如,apache,、,gcc,、,gdb,等,应用编程,在更高层次的编程接口或者库之上构建应用程序。如,android,程序(,android sdk,)、,iphone,程序(,iphone sdk,)、,QT,程序设计(,QT,),MFC,程序设计(,MFC,)等。,3,系统资源,处理器,输入输出,进程管理,内存,设备,定时器,进程间通信,网络,4,系统调用在系统中所处的位置,所有操作系统都提供多种服务的入口点,由此程序向系统核请求服务。这些入口点被称之为系统调用,(system call),,,5,C,库,这里我们所说的,C,库(,libc,),指的是标准,C,定义的函数的集合。如标准输入输出函数、字符串处理函数、动态存储分配函数、日期时间函数、数学函数等。,GNU,发布的,libc,称为,glibc,6,系统调用与,C,库关系,系统调用与库从形式上来看都,C,函数,C,库函数有些是调用系统调用来实现的,比如说,malloc,、,free,调用,brk,,,printf,调用,write,系统用,有些函数不需要任何系统调用,比如,abs,、,strcpy,、,atoi,等,因为它并不是必需要使用内核服务,系统调用通常提供的是最小界面,而库函数通常提供更复杂的功能。,7,内核如何处理系统调用,每个系统调用被赋予一个系统调用号,在,i386,平台上,执行一个系统调用是通过,int 0 x80,指令完成的。,eax,存放系统调用号,ebx,、,ecx,、,edx,、,esi,、,edi,存储系统调用参数,对于超过,5,个参数的系统调用,用一个寄存器指向用户空间存储所有系统调用参数的缓存。,8,错误处理,在系统编程中错误通常通过函数返回值来表示,并通过特殊变量,errno,来描述。,errno,这个全局变量在,头文件中声明如下:,extern int errno;,错误处理函数,perror,strerror,9,错误代码,E2BIG,参数列表太长,EACCESS,权限不足,EAGAIN,重试,EBADF,错误的文件描述符,EBUSY,设备或资源忙,ECHILD,无子进程,EDOM,数学参数不在函数域内,EEXIST,文件已存在,EFAULT,地址错误,EFBIG,文件太大,EINTR,系统调用被中断,.,10,文件与,I/O,(一),第四章,11,本章目标,什么是,I/O,文件描述符,文件系统调用,12,什么是,I/O,输入,/,输出是主存和外部设备之间拷贝数据的过程,设备,-,内存(输入操作),内存,-,设备(输出操作),高级,I/O,ANSI C,提供的标准,I/O,库称为高级,I/O,,通常也称为带缓冲的,I/O,低级,I/O,通常也称为不带缓冲的,I/O,13,文件描述符,对于,Linux,而言,所有对设备或文件的操作都是通过文件描述符进行的。,当打开或者创建一个文件的时候,内核向进程返回一个文件描述符(非负整数)。后续对文件的操作只需通过该文件描述符,内核记录有关这个打开文件的信息。,一个进程启动时,默认打开了,3,个文件,标准输入、标准输出、标准错误,对应文件描述符是,0,(,STDIN_FILENO,)、,1,(,STDOUT_FILENO,)、,2,(,STDERR_FILENO,),这些常量定义在,unistd.h,头文件中。,14,文件描述符与文件指针转换,fileno,:将文件指针转换为文件描述符,fdopen,:将文件描述符转换为文件指针,15,文件系统调用,open,系统调用,close,系统调用,creat,系统调用,read,系统调用,write,系统调用,16,open,系统调用,2-1,有几种方法可以获得允许访问文件的文件描述符。最常用的是使用,open,()(打开)系统调用,函数原型,int open(const char*path,int flags);,参数,path,:文件的名称,可以包含(绝对和相对)路径,flags,:文件打开模式,返回值,打开成功,返回文件描述符;,打开失败,返回,1,open,系统调用,2-2,函数原型,int open(const char*path,int flags,mode_t mode);,参数,path,:文件的名称,可以包含(绝对和相对)路径,flags,:文件打开模式,mode:,用来规定对该文件的所有者,文件的用户组及系 统中其他用户的访问权限,返回值,打开成功,返回文件描述符;,打开失败,返回,1,打开文件的方式,打开方式,描述,O_RDONLY,打开一个供读取的文件,O_WRONLY,打开一个供写入的文件,O_RDWR,打开一个可供读写的文件,O_APPEND,写入的所有数据将被追加到文件的末尾,O_CREAT,打开文件,如果文件不存在则建立文件,O_EXCL,如果已经置,O_CREAT,且文件存在,则强制,open,()失败,O_TRUNC,在,open,()时,将文件的内容清空,所有这些标志值的符号名称可以通过,#include,访问,访问权限,打开方式,描述,S_IRUSR,文件所有者的读权限位,S_IWUSR,文件所有者的写权限位,S_IXUSR,文件所有者的执行权限位,S_IRWXU,S_IRUSR|S_IWUSR|S_IXUSR,S_IRGRP,文件用户组的读权限位,S_IWGRP,文件用户组的写权限位,S_IXGRP,文件用户组的执行权限位,S_IRWXG,S_IRGRP|S_IWGRP|S_IXGRP,S_IROTH,文件其他用户的读权限位,S_IWOTH,文件其他用户的写权限位,S_IXOTH,文件其他用户的执行权限位,S_IRWXO,S_IROTH|S_IWOTH|S_IXOTH,open,调用的几点说明,可以利用按位逻辑加,(bitwise-OR)(|),对打开方式的标志值进行组合。,如打开一个新文件:,define NEWFILE(O_WRONLY|O_CREAT|O_TRUNC),对访问权限位进行访问所用到的标识符,均可以通过,include,访问到,同样可以通过,|,运算来对访问权限进行组合,#define MODE755 (S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH),close,系统调用,为了重新利用文件描述符,用,close(),系统调用释放打开的文件描述符,函数原型:,int close(int fd);,函数参数:,fd,:要关闭的文件的文件描述符,返回值,如果出现错误,返回,-1,调用成功返回,0,creat,系统调用,2-1,为了维持与早期的,UNIX,系统的向后兼容性,,Linux,也提供可选的创建文件的系统调用,它称为,creat(),。,函数原型:,int creat(const char*path,mode_t mode),;,参数,path,:文件的名称,可以包含(绝对和相对)路径,mode:,用来规定对该文件的所有者,文件的用户组及系 统中其他用户的访问权限,返回值,打开成功,返回文件描述符;,打开失败,返回,1,creat,系统调用,(2-2),在,UNIX,的早期版本中,,open(),系统调用仅仅存在两个参数的形式。如文件不存在,它就不能打开这些文件。文件的创建则由单独的系统调用,creat(),完成。在,Linux,及所有,UNIX,的近代版本中,,creat(),系统调用是多余的。,creat(),调用,fd=creat(file,mode),;,完全等价于近代的,open(),调用,fd=open(file,O_WRONLY|O_CREAT|O_TRUNC,mode),;,read,系统调用,一旦有了与一个打开文件描述相连的文件描述符,只要该文件是用,O_RDONLY,或,O_RDWR,标志打开的,就可以用,read(),系统调用从该文件中读取字节,函数原型:,ssize_t read(int fd,void*buf,size_t count);,参数,fd,:想要读的文件的文件描述符,buf,:,指向内存块的指针,从文件中读取来的字节放到这个内存块中,count,:,从该文件复制到,buf,中的字节个数,返回值,如果出现错误,返回,-1,读文件结束,返回,0,否则返回从该文件复制到规定的缓冲区中的字节数,write,系统调用,用,write(),系统调用将数据写到一个文件中,函数原型:,ssize_t write(int fd,const void*buf,size_t count);,函数参数:,fd,:要写入的文件的文件描述符,buf,:指向内存块的指针,从这个内存块中读取数据写入 到文件中,count,:要写入文件的字节个数,返回值,如果出现错误,返回,-1,如果写入成功,则返回写入到文件中的字节个数,文件与,I/O,(二),第五章,27,本章目标,read,、,write,lseek,目录访问(,opendir,、,readdir,、,closedir,),rmdir,、,mkdir,chmod,、,fchmod,chown,、,fchown,28,read,系统调用,一旦有了与一个打开文件描述相连的文件描述符,只要该文件是用,O_RDONLY,或,O_RDWR,标志打开的,就可以用,read(),系统调用从该文件中读取字节,函数原型:,ssize_t read(int fd,void*buf,size_t count);,参数,fd,:想要读的文件的文件描述符,buf,:,指向内存块的指针,从文件中读取来的字节放到这个内存块中,count,:,从该文件复制到,buf,中的字节个数,返回值,如果出现错误,返回,-1,读文件结束,返回,0,否则返回从该文件复制到规定的缓冲区中的字节数,write,系统调用,用,write(),系统调用将数据写到一个文件中,函数原型:,ssize_t write(int fd,const void*buf,size_t count);,函数参数:,fd,:要写入的文件的文件描述符,buf,:指向内存块的指针,从这个内存块中读取数据写入 到文件中,count,:要写入文件的字节个数,返回值,如果出现错误,返回,-1,如果写入成功,则返回写入到文件中的字节个数,文件的随机读写,到目前为止的所有文件访问都是顺序访问。这是因为所有的读和写都从当前文件的偏移位置开始,然后文件偏移值自动地增加到刚好超出读或写结束时的位置,使它为下一次访问作好准备。,有个文件偏移这样的机制,在,Linux,系统中,随机访问就变得很简单,你所需做的只是将当前文件移值改变到有关的位置,它将迫使一次,read(),或,write(),发生在这一位置。,(,除非文件被,O_APPEND,打开,在这种情况下,任何,write,调用仍将发生在文件结束处,),lseek,系统调用,1,功能说明:,通过指定相对于开始位置、当前位置或末尾位置的字节数来重定位,curp,,这取决于,lseek(),函数中指定的位置,原型:,off_t lseek(int fd,off_t offset,int base);,需设置的文件标识符,偏移量,搜索的起始位置,返回值:返回新的文件偏移值,lseek,系统调用,2,base,表示搜索的起始位置,有以下几个值:(这些值定义在,),base,文件位置,SEEK_SET,从文件开始处计算偏移,SEEK_CUR,从当前文件的偏移值计算偏移,SEEK_END,从文件的结束处计算偏移,目录访问,3,1,功能说明:打开一个目录,原型:,DIR*opendir(char*pathname);,返回值:,打开成功,返回一个目录指针,打开失败,则返回,0,文件的路径名,目录访问,3,2,功能说明:,访问指定目录中下一个连接的细节,原型:,struct dirent*readdir(DIR *dirptr);,返回值:,返回一个指向,dirent,结构的指针,它包含指定目录中下一个连接的细节;,没有更多连接时,返回,0,目录指针,目录访问,3,3,功能说明:,关闭一个已经打开的目录,原型:,int closedir(DIR *dirptr);,返回值:调用成功返回,0,,失败返回,-1,目录指针,目录信息结构体,struct dirent,long d_ino;/*inode number*/,off_t d_off;/*offset to this dirent*/,unsigned short d_reclen;/*length of this d_name*/,char d_name NAME_MAX+1;/*file name(null-terminated)*/,mkdir,系统调用,功能说明:,用来创建一个称为,pathname,的新目录,它的权限位设置为,mode,原型:,int mkdir(char*pathname,mode_t mode);,返回值:调用成功返回,0,,失败返回,-1,文件的路径名,权限位,rmdir,系统调用,功能说明:,删除一个空目录,原型:,int rmdir(char*pathname);,返回值:调用成功返回,0,,失败返回,-1,文件的路径名,chmod,和,fchmod,系统调用,功能说明:,用来改变给定路径名,pathname,的文件的权限位,原型:,int chmod(char*pathname,mode_t mode);,文件的路径名,权限位,返回值:调用成功返回,0,,失败返回,-1,int fchmod(int fd,mode_t mode);,文件描述符,权限位,chown,和,fchown,系统调用,功能说明:,用来改变文件所有者的识别号,(owner id),或者它的用户组识别号,(group ID),原型:,int chown(char*pathname,uid_t owner,gid_t group);,文件的路径名,所有者识别号,返回值:调用成功返回,0,,失败返回,-1,int fchown(int fd,uid_t owner,gid_t group,);,文件描述符,用户组识别号,所有者识别号,用户组识别号,文件与,I/O,(三),第六章,42,本章目标,stat,stat,结构体,stat,示例,43,stat,功能:读取文件元数据,44,int stat(const char*path,struct stat*buf);,int fstat(int fd,struct stat*buf);,int lstat(const char*path,struct stat*buf);,stat,结构体,struct stat,dev_t st_dev;/*ID of device containing file*/,ino_t st_ino;/*inode number*/,mode_t st_mode;/*protection*/,nlink_t st_nlink;/*number of hard links*/,uid_t st_uid;/*user ID of owner*/,gid_t st_gid;/*group ID of owner*/,dev_t st_rdev;/*device ID(if special file)*/,off_t st_size;/*total size,in bytes*/,blksize_t st_blksize;/*blocksize for file system I/O*/,blkcnt_t st_blocks;/*number of 512B blocks allocated*/,time_t st_atime;/*time of last access*/,time_t st_mtime;/*time of last modification*/,time_t st_ctime;/*time of last status change*/,;,45,课后作业,实现,ls-l,功能,lstat,getpwuid,getgrgid,readlink,46,文件与,I/O,(四),第七章,47,本章目标,文件共享,打开文件内核数据结构,一个进程两次打开同一个文件,两个进程打开同一个文件,复制文件描述符(,dup,、,dup2,、,fcntl,),48,文件共享(,3,1,),49,文件状态标志:,读、写、追加、同步、非阻塞等,文件共享(,3,2,),50,文件共享(,3,3,),51,复制文件描述符,52,执行,dup(3),前后,复制文件描述符,复制文件描述符有三种方法,dup,dup2,fcntl,fcntl(fd,F_DUPFD,fd_start);,53,文件与,I/O,(五),第八章,54,本章目标,fcntl,函数,fcntl,常用操作,文件锁,55,fcntl,功能:操纵文件描述符,改变已打开的文件的属性,56,int fcntl(int fd,int cmd,./*arg*/);,fcntl,常用操作,复制文件描述符,F_DUPFD(long),文件描述符标志,F_GETFD(void),F_SETFD(long),文件状态标志,F_GETFL(void),F_SETFL(long),文件锁,F_GETLK,F_SETLK,,,F_SETLKW,57,文件锁结构体,struct flock,.,short l_type;/*Type of lock:F_RDLCK,F_WRLCK,F_UNLCK*/,short l_whence;/*How to interpret l_start:,SEEK_SET,SEEK_CUR,SEEK_END*/,off_t l_start;/*Starting offset for lock*/,off_t l_len;/*Number of bytes to lock*/,pid_t l_pid;/*PID of process blocking our lock,(F_GETLK only)*/,.,;,58,进程(一),第九章,59,本章目标,什么是程序,什么是进程,进程数据结构,进程与程序区别与联系,60,程序是完成特定任务的一系列指令集合。,什么是程序,从用户的角度来看进程是程序的一次执行过程,从操作系统的核心来看,进程是操作系统分配的内存、,CPU,时间片等资源的基本单位。,进程是资源分配的最小单位,每一个进程都有自己独立的地址空间与执行状态。,像,UNIX,这样的多任务操作系统能够让许多程序同时运行,每一个运行着的程序就构成了一个进程,什么是进程,代码段,数据段,堆栈段,PCB,我们,进程的静态描述:由三部分组成,:,PCB,、有关程序段和该程序段对其进行操作的数据结构集。,进程控制块:用于描述进程情况及控制进程运行所需的全部信息。,代码段:是进程中能被进程调度程序在,CPU,上执行的程序代码段。,数据段:一个进程的数据段,可以是进程对应的程序加工处理的原始数据,也可以是程序执行后产生的中间或最终数据,进程数据结构,进程是动态的,程序是静态的,进程的生命周期是相对短暂的,而程序是永久的。,进程数据结构,PCB,一个进程只能对应一个程序,一个程序可以对应多个进程。,进程与程序,进程(二),第十章,65,本章目标,进程状态变迁,进程控制块,进程创建,进程撤消,终止进程的五种方法,66,就绪,等待,运行,进程状态变迁,进程状态变迁,运行状态(,TASK_RUNNING,),可中断睡眠状态(,TASK_INTERRUPTIBLE,),不可中断睡眠状态(,TASK_UNINTERRUPTIBLE,),暂停状态(,TASK_STOPPED,),僵死状态(,TASK_ZOMBIE,),进程状态变迁,进程,描述,信息,进程标识符用于唯一的标识一个进程。,进程控制信息,进程当前状态,进程优先级,程序开始地址,各种计时信息,通信信息,资源信息,占用内存大小及管理用数据结构指针,交换区相关信息,I/O,设备号、缓冲、设备相关的数结构,文件系统相关指针,现场保护信息,寄存器,PC,程序状态字,PSW,栈指针,进程控制块,每个进程都会分配到一个独一无二的数字编号,我们称之为,“,进程标识,”,(process identifier),或者就直接叫它,PID.,是一个正整数,取值范围从,2,到,32768,当一个进程被启动时,它会顺序挑选下一个未使用的编号数字做为自己的,PID,数字,1,一般为特殊进程,init,保留的,进程标识,不同的操作系统所提供的进程创建原语的名称和格式不尽相同,但执行创建进程原语后,操作系统所做的工作却大致相同,都包括以下几点:,给新创建的进程分配一个内部标识,,在内核中建立进程结构,。,复制父进程的环境,为进程分配资源,,包括进程映像所需要的所有元素(程序、数据、用户栈等),,复制父进程,地址空间,的内容到该进程,地址,空间中。,置该进程的状态为就绪,插入就绪队列。,进程创建,进程终止时操作系统做以下工作:,关闭软中断,:,因为进程即将终止而不再处理任何软中断信号;,回收资源:,释放进程分配的所有资源,如关,闭所有已打开文件,,释放进程相应的数据结构等,;,写记帐信息,:将进程在运行过程中所产生的记帐数据(其中包括进程运行时的各种统计信息)记录到一个全局记帐文件中;,置该进程为僵死状态,:,向父进程发送子进程死的软中断信号,将终止信息,status,送到指定的存储单元中;,转进程调度,:,因为此时,CPU,已经被释放,需要由进程调度进行,CPU,再分配。,进程撤消,从,main,函数返回,调用,exit,调用,_exit,调用,abort,由信号终止,终止进程的五种方法,进程(三),第十一章,75,本章目标,复制进程映像,fork,系统调用,孤儿进程、僵尸进程,写时复制,76,使用,fork,函数得到的子进程从父进程的继承了整个进程的地址空间,包括:进程上下文、进程堆栈、内存信息、打开的文件描述符、信号控制设置、进程优先级、进程组号、当前工作目录、根目录、资源限制、控制终端等。,子进程与父进程的区别在于:,1,、父进程设置的锁,子进程不继承,2,、各自的进程,ID,和父进程,ID,不同,3,、子进程的未决告警被清除;,4,、子进程的未决信号集设置为空集。,复制一个进程映象,fork,包含头文件,和,函数功能,:,创建一个子进程,函数原型,pid_t fork(void);,参数:无参数。,返回值,:,如果成功创建一个子进程,对于父进程来说返回子进程,ID,如果成功创建一个子进程,对于子进程来说返回值为,0,如果为,-1,表示创建失败,fork,系统调用,fork,系统调用,fork,系统调用之后,父子进程将交替执行。,如果父进程先退出,子进程还没退出那么子进程的父进程将变为,init,进程。(注:任何一个进程都必须有父进程),如果子进程先退出,父进程还没退出,那么子进程必须等到父进程捕获到了子进程的退出状态才真正结束,否则这个时候子进程就成为僵进程。,fork,系统调用注意点,如果多个进程要读取它们自己的那部分资源的副本,那么复制是不必要的。,每个进程只要保存一个指向这个资源的指针就可以了。,如果一个进程要修改自己的那份资源的“副本”,那么就会复制那份资源。这就是写时复制的含义,写时复制,copy on write,进程(四),第十二章,82,本章目标,fork,之后父子进程共享文件,fork,与,vfork,exit,与,_exit,atexit,execve,替换进程映像(加载程序),83,fork,之后父子进程共享文件,84,fork,与,vfork,在,fork,还没实现,copy on write,之前。,Unix,设计者很关心,fork,之后立刻执行,exec,所造成的地址空间浪费,所以引入了,vfork,系统调用。,vfork,有个限制,子进程必须立刻执行,_exit,或者,exec,函数。,即使,fork,实现了,copy on write,,效率也没有,vfork,高,但是我们不推荐使用,vfork,,因为几乎每一个,vfork,的实现,都或多或少存在一定的问题。,85,进程的五种终止方式,正常退出,从,main,函数返回,调用,exit,调用,_exit,异常退出,调用,abort,由信号终止,86,exit,与,_exit,87,进程运行,调用终止处理程序,清除,I/O,缓冲,内核,进程终止运行,_exit,exit,atexit,atexit,可以注册终止处理程序,,ANSI C,规定最多可以注册,32,个终止处理程序。,终止处理程序的调用与注册次序相反,88,int atexit(void(*function)(void);,execve,替换进程映像,89,int execve(const char*filename,char*const argv,char*const envp);,进程(五),第十三章,90,本章目标,exec,替换进程映像,exec,关联函数组(,execl,、,execlp,、,execle,、,execv,、,execvp,),91,exec,替换进程映象,在进程的创建上,Unix,采用了一个独特的方法,它将进程创建与加载一个新进程映象分离。这样的好处是有更多的余地对两种操作进行管理。,当我们创建了一个进程之后,通常将子进程替换成新的进程映象,这可以用,exec,系列的函数来进行。当然,,exec,系列的函数也可以将当前进程替换掉。,92,exec,关联函数组,包含头文件,功能用,exec,函数可以把当前进程替换为一个新进程。,exec,名下是由多个关联函数组成的一个完整系列,头文件,原型,int execl(const 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);,参数,path,参数表示你要启动程序的名称包括路径名,arg,参数表示启动程序所带的参数,返回值,:,成功返回,0,失败返回,-1,93,execl,,,execlp,,,execle,(都带,“,l,”,),的参数个数是可变的,参数以一个空指针结束。,execv,和,execvp,的第二个参数是一个字符串数组,新程序在启动时会把在,argv,数组中给定的参数传递到,main,这些函数通常都是用,execve,实现的,这是一种约定俗成的做法,并不是非这样不可。,exec,关联函数组,名字最后一个字母是,“,p,”,的函数会搜索,PATH,环境变量去查找新程序的可执行文件。如果可执行文件不在,PATH,定义的路径上,就必须把包括子目录在内的绝对文件名做为一个参数传递给这些函数,exec,关联函数组,进程(六),第十四章,96,本章目标,SIGCHLD,wait,waitpid,僵进程,system,97,SIGCHLD,当子进程退出的时候,内核会向父进程发送,SIGCHLD,信号,子进程的退出是个异步事件(子进程可以在父进程运行的任何时刻终止),子进程退出时,内核将子进程置为僵尸状态,这个进程称为僵尸进程,它只保留最小的一些内核数据结构,以便父进程查询子进程的退出状态。,父进程查询子进程的退出状态可以用,wait/waitpid,函数,98,头文件,和,函数功能,:,当我们用,fork,启动一个进程时,子进程就有了自己的生命,并将独立地运行。有时,我们需要知道某个子进程是否已经结束了,我们可以通过,wait,安排父进程在子进程结束之后,。,函数原型,pid_t wait(int*stat,us,),函数参数,stat,us,:,该参数可以获得你等待子进程的信息,返回值:,成功等待子进程函数返回等待子进程的,ID,wait,wait,系统调用会使父进程暂停执行,直到它的一个子进程结束为止。,返回的是子进程的,PID,,它通常是结束的子进程,状态信息允许父进程判定子进程的退出状态,即从子进程的,main,函数返回的值或子进程中,exit,语句的退出码。,如果,status,不是一个空指针,状态信息将被写入它指向的位置,wait,宏定义,描述,WIFEXITED(status),如果子进程正常结束,返回一个非零值,WEXITSTATUS(status),如果,WIFEXITED,非零,返回子进程退出码,WIFSIGNALED(status),子进程因为捕获信号而终止,返回非零值,WTERMSIG(status),如果,WIFSIGNALED,非零,返回信号代码,WIFSTOPPED(status),如果子进程被暂停,返回一个非零值,WSTOPSIG(status),如果,WIFSTOPPED,非零,返回一个信号代码,这些宏在,sys/wait.h,头文件里定义,wait,函数功能,:,用来等待某个特定进程的结束,函数原型,:,pid_t waitpid(pid_t pid,int*status,int options),参数,:,status:,如果不是空,会把状态信息写到它指向的位置,options,:允许改变,waitpid,的行为,最有用的一个选项是,WNOHANG,它的作用是防止,waitpid,把调用者的执行挂起,返回值:如果成功返回等待子进程的,ID,,失败返回,-1,waitpid,waitpid,函数说明,对于,waitpid,的,p i d,参数的解释与其值有关:,pid,=-1,等待任一子进程。于是在这一功能方面,waitpid,与,wait,等效。,pid,0,等待其进程,I D,与,p i d,相等的子进程。,pid,=0,等待其组,I D,等于调用进程的组,I D,的任一子进程。换句话说是与调用者进程同在一个组的进程。,pid,-1,等待其组,I D,等于,p i d,的绝对值的任一子进程。,在一个子进程终止前,,wait,使其调用者阻塞,而,waitpid,有一选择项,可使调用者不阻塞。,waitpid,并不等待第一个终止的子进程,它有若干个选择项,可以控制它所等待的特定进程。,实际上,wait,函数是,waitpid,函数的一个特例。,wait,和,waitpid,的区别,当一个子进程结束运行时,它与其父进程之间的关联还会保持到父进程也正常地结束运行或者父进程调用了,wait,才告终止。,进程表中代表子进程的数据项是不会立刻释放的,虽然不再活跃了,可子进程还停留在系统里,因为它的退出码还需要保存起来以备父进程中后续的,wait,调用使用。它将称为一个“僵进程”。,僵进程,调用,wait,或者,waitpid,函数,查询子进程退出状态,,此方法父进程会被挂起,。,如果不想让父进程挂起,可以在父进程中加入一条语句:,signal(SIGCHLD,SIG_IGN);,表示父进程忽略,SIGCHLD,信号,该信号是子进程退出的时候向父进程发送的。,如何避免僵进程,system,功能:,system()函数调用“/bin/sh-c command”执行特定的命令,阻塞当前进程直到command命令执行完毕,原型:,int system(const char*command);,返回值:,如果无法启动,shell,运行命令,,system,将返回,127,;出现不能执行,system,调用的其他错误时返回,-1,。如果,system,能够顺利执行,返回那个命令的退出码。,system,函数执行时,会调用,fork,、,execve,、,waitpid,等函数。,107,my_system,int my_system(const char*command),pid_t pid;,int status;,if(command=NULL),return 1;,if(pid=fork()0),status=-1;,else if(pid=0),execl(/bin/sh,sh,-c,command,NULL);,exit 127;,108,my_system,else,while(waitpid(pid,&status,0)0),if(errno=EINTR),continue;,status=-1;,break;,return status;,109,进程(七),第十五章,110,本章目标,什么是守护进程,守护进程的创建步骤,daemon,111,什么是守护进程,守护进程是在后台运行不受控端控制的进程,通常情况下守护进程在系统启动时自动运行,守护进程的名称通常以,d,结尾,比如,sshd,、,xinetd,、,crond,等,112,创建守护进程步骤,调用,fork(),创建新进程,它会是将来的守护进程,在父进程中调用,exit,,保证子进程不是进程组组长,调用,setsid,创建新的会话期,将当前目录改为根目录,将标准输入、标准输出、标准错误重定向到,/dev/null,113,daemon,114,int daemon(int nochdir,int noclose);,功能:创建一个守护进程,参数:,nochdir,:,=0,将当前目录更改至“,/”,noclose,:,=0,将标准输入、标准输出、标准错误重定向至“,/dev/null,”,信号(一),第十六章,115,本章目标,中断,信号,信号与中断,signal,116,中断,中断是系统对于异步事件的响应,中断信号,中断源,现场信息,中断处理程序,中断向量表,117,中断分类,硬件中断(外部中断),外部中断是指由外部设备通过硬件请求的方式产生的中断,也称为硬件中断,软件中断(内部中断),内部中断是由,CPU,运行程序错误或执行内部程序调用引起的一种中断,也称为软件中断。,118,信号,信号是,UNIX,系统响应某些状况而产生的事件,进程在接收到信号时会采取相应的行动。,信号是因为某些错误条件而产生的,比如内存段冲突、浮点处理器错误或者非法指令等,信号是在软件层次上对中断的一种模拟,所以通常把它称为是软中断,119,信号与中断,信号与中断的相似点:,(,1,)采用了相同的异步通信方式;,(,2,)当检测出有信号或中断请求时,都暂停正在执行的程序而转去执行相应的处理程序;,(,3,)都在处理完毕后返回到原来的断点;,(,4,)对信号或中断都可进行屏蔽。,信号与中断的区别:,(,1,)中断有优先级,而信号没有优先级,所有的信号都是平等的;,(,2,)信号处理程序是在用户态下运行的,而中断处理程序是在核心态下运行;,(,3,)中断响应是及时的,而信号响应通常都有较大的时间延迟。,120,信号的名称是在头文件,signal.h,里定义的,信号名称,描述,SIGABRT,进程停止运行,SIGALRM,警告钟,SIGFPE,算述运算例外,SIGHUP,系统挂断,SIGILL,非法指令,SIGINT,终端中断,SIGKILL,停止进程,(,此信号不能被忽略或捕获,),SIGPIPE,向没有读者的管道写入数据,SIGSEGV,无效内存段访问,信号名称,信号名称,描述,SIGQUIT,终端退出,SIGTERM,终止,SIGUSR1,用户定义信号,1,SIGUSR2,用户定义信号,2,SIGCHLD,子进程已经停止或退出,SIGCONT,如果被停止则继续执行,SIGSTOP,停止执行,SIGTSTP,终端停
展开阅读全文

开通  VIP、SVIP  下载更划算
下载10份以上建议开通 VIP 会员
下载20份以上建议开通SVIP会员


开通VIP      成为共赢上传

当前位置:首页 > 包罗万象 > 大杂烩

移动网页_全站_页脚广告1

关于我们      便捷服务       自信AI       AI导航        关注我们

©2010-2026 宁波自信网络信息技术有限公司  版权所有

客服电话:0574-28810668  投诉电话:18658249818

gongan.png浙公网安备33021202000488号   

icp.png浙ICP备2021020529号-1  |  浙B2-20240490  

关注我们 :微信公众号    抖音    微博    LOFTER 

客服