CH1网络编程基础.ppt

上传人:牧羊曲112 文档编号:5421248 上传时间:2023-07-05 格式:PPT 页数:167 大小:527.50KB
返回 下载 相关 举报
CH1网络编程基础.ppt_第1页
第1页 / 共167页
CH1网络编程基础.ppt_第2页
第2页 / 共167页
CH1网络编程基础.ppt_第3页
第3页 / 共167页
CH1网络编程基础.ppt_第4页
第4页 / 共167页
CH1网络编程基础.ppt_第5页
第5页 / 共167页
点击查看更多>>
资源描述

《CH1网络编程基础.ppt》由会员分享,可在线阅读,更多相关《CH1网络编程基础.ppt(167页珍藏版)》请在三一办公上搜索。

1、,TCP/IP与网络编程,授课教师 李平勇成都大学信息科学与技术学院,第1章 网络编程基础,网络操作系统(Network Operating System,NOS)网络操作系统是使网络上的计算机能方便而有效地共享网络资源,为网络用户提供所需的各种服务软件和有关规程的集合。它除了具有一般桌面操作系统的全部功能外,还应该满足用户使用网络的需要,尤其要提供数据在网上的安全传输,管理网络中的共享资源,实现用户通信以及方便用户使用网络。网络操作系统是作为网络用户与网络系统之间的接口。网络操作系统的任务有两项:(1)常规任务,主要负责文件管理、存储管理、进程管理、任务管理、I/O管理、CPU调度等;(2)

2、网络任务,主要功能为资源共享(文件、设备、数据)、安全管理、远程过程调用、网络I/O等。,1.1 网络操作系统,网络操作系统,目前主流的四种主要网络操作系统是:UNIX或Linux。其中,UNIX操作系统主要有SUN公司的Solaris,IBM公司的AIX等。Linux操作系统主要有Redhat,红旗Linux等。Windows操作系统:Microsoft公司的Windows系列,如Microsoft的NT 或Windows 2003 Advanced Server等。Novell公司的Novell网(NetWare)Santa Cruz Operation公司(SCO)的UnixWare,U

3、NIX,UNIX是一个多用户、多任务的分时操作系统,在计算机网络尤其是Internet的发展中发挥了极其重要的作用。在Internet中提供服务的各类节点计算机中,90%以上都使用UNIX或类UNIX操作系统。,UNIX系统结构图,UNIX,UNIX系统主要由以下4个部分组成:内核。是组成操作系统的核心,它控制任务的调度运行,管理计算机存储器,维护文件系统,并在用户中分配计算机资源。它对用户是透明的。外壳(Shell)。Shell是一个程序(类似于DOS中的COMMAND.COM),它解释用户所提交的命令并把该命令提交给内核执行,执行结果再返回给用户。Shell也是一种程序设计语言,用户可以使

4、用Shell命令来设计程序(类似于DOS中的batch命令)。文件系统。文件系统是指在用户终端上可为用户所用的全部文件的集合,它使信息的存储和检索更为容易。命令。命令是一组实用程序的名称。UNIX系统提供的命令包括:文本编辑、文件管理、软件开发工具、系统配置、通信等。,UNIX,UNIX中包含3个主要的网络包:TCP/IP 包括TCP、UDP、IP、DNS等标准协议。基本网络实用程序(BNU)提供UUCP、远程登录、远程执行、发送邮件、连接远地终端、串行通信等功能。网络文件系统(Network File System,NFS)实现不同系统间文件和目录的透明访问,这种文件共享方式独立于计算机、操

5、作系统和网络体系结构。,Linux,UNIX系统是一个非常成熟的网络操作系统,但对计算机硬件的要求比较高,对于一般的个人用户来说,想要在PC机上运行UNIX是比较困难的。Linux是按照UNIX风格设计的操作系统,所以在源代码级上兼容绝大部分的UNIX标准。相当多的网络安全人员在自己的机器上运行的正是Linux。,Linux,Linux是一个充满生机的操作系统,具有巨大的用户群和广泛的应用领域,在软件业中有着重要地位,是惟一能与UNIX和Windows较量和抗衡的操作系统。从技术上讲,Linux有如下特点:(1)继承了UNIX的优点,又有了许多更好的改进,其开放、协的开发模式是集体智慧的结晶,

6、能紧跟技术发展潮流,具有极强的生命力;(2)是通用的操作系统,可用于各种PC机和工作站;(3)内置通信联网功能,可让异种机联网;(4)具有开放的源代码,有利于发展各种特色的操作系统;(5)符合POSIX标准,各种UNIX应用可方便地移植到Linux下;(6)提供庞大的管理功能和远程管理功能;(7)支持大量外部设备;(8)支持32种文件系统;(9)提供GUI;(10)支持并行处理和实时处理,能充分发挥硬件性能;(11)在Linux平台上软件开发成本低。,Windows,Microsoft(微软)公司的Windows系统不仅在个人操作系统中占有绝对优势,它在网络操作系统中也具有非常强劲的竞争力。W

7、indows操作系统配置在整个局域网配置中是最常见的,但由于它对服务器的硬件要求较高,且稳定性能不是很高,所以Windows网络操作系统一般只是用在中低档服务器中,高端服务器通常采用UNIX、Linux或Solaris等非Windows操作系统。在局域网中,Windows网络操作系统主要有:Windows NT 4.0 Server、Windows 2000 Server/Advance Server,以及Windows 2003 Server/Advance Server等。工作站系统可以采用任何Windows或非Windows操作系统,包括个人操作系统,如Windows 9x/ME/XP等

8、。,Windows NT系统结构,Windows,Windows NT作为一款成功的网络操作系统,其网络功能强大,采用OSI/RM网络体系结构,在多个层次之间提供接口规范,如NDIS、TDI、Provider Interface、Socket、NETBIOS等,支持TCP/IP、IPX/SPX、NETBEUI等网络协议,如下页图中所示。,Windows NT网络体系结构,Windows API函数,WIN32 API是Microsoft Windows 32位平台的应用程序编程接口。WIN32 API函数是构筑Windows应用框架的基石,在它的下面是Windows的操作系统核心,上面则是所有

9、的Windows应用程序,如下图所示。,Windows API函数,Windows API函数根据功能不同,分为很多种类,具体如下:网络函数消息函数文件处理函数打印函数文本和字体函数菜单函数位图、图标和光栅运算函数绘图函数设备场景函数硬件与系统函数进程和线程函数控件与消息函数,Windows API函数,目前常用的可视化编程环境(如VB、VC+、DELPHI等)中提供了大量的类库和各种控件,它们替代了API的神秘功能,事实上这些类库和控件都是构架在WIN32 API函数基础之上的,是封装了的API函数的集合。它们把常用的API函数组合在一起成为一个控件或类库,并赋予其方便的使用方法,极大地加速

10、了Windows应用程序开发的过程。实际上如果要开发出更灵活、更实用、更具效率的应用程序,必然要涉及到直接使用API函数,虽然类库和控件使应用程序的开发简单的多,但它们只提供WINDOWS的一般功能,对于比较复杂和特殊的功能来说,使用类库和控件是非常难以实现的,这时就需要采用API函数来实现。,1.2 文件系统,在网络通信中,许多通信方式(如Socket通信、管道通信、邮路通信等)的基本原理都与UNIX/Linux的文件操作相同,所以,了解UNIX/Linux下的文件操作是学习网络通信的基础。,Linux支持多种文件系统,如ext2、ext3、minix、iso9660、fat、vfat、nf

11、s等。在这些具体文件系统的上层,Linux提供了虚拟文件系统(VFS)来隐藏各种文件系统的具体细节,为访问它们提供统一的接口。,1.2 文件系统,文件系统,虚拟文件系统,应用程序,Ext2,设备文件,FAT,NFS,文件编程,Linux中对文件编程可以使用两类函数:Linux系统调用C语言库函数 前者依赖于Linux系统,后者与操作系统是独立的,在任何操作系统下,使用C语言库函数操作文件的方法都是相同的。,系统调用-创建,int creat(const char*filename,mode_t mode)Filename:要创建的文件名(包含路径,缺省为当前路径)Mode:创建模式,系统调用-

12、创建,Mode 含义S_IRUSR 可读S_IWUSR 可写S_IXUSR 可执行S_IRWXU 可读、写、执行S_IRGRP 组可以读S_IWGRP 组可以写S_IXGRP 组可以执行,系统调用-创建,Mode 含义S_IRWXG 组可以读写执行S_IROTH 其他人可以读S_IWOTH 其他人可以写S_IXOTH 其他人可以执行S_IRWXO 其他人可以读、写、执行S_ISUID 设置用户执行IDS_ISGID 设置组的执行ID,系统调用-创建,除了可以通过上述宏进行标志以外,也可以用数字来表示,Linux共用5个数字来表示文件的各种权限:第一位:用户ID;第二位:组ID;第三位:用户自己

13、的权限;第四位:组的权限;第五位:其他人的权限。,系统调用-创建,每个数字可以取1(执行权限)、2(写权限)、4(读权限)、0(无任何权限)或者这些值的和。例:要创建一个用户可读、可写、可执行,但是组没有权限,其他人可以读、可以执行的文件,并设置用户ID位。10705:1(用户ID)、0(不设置组ID)、7(1+2+4,读、写、执行)、0(没有权限)、5(1+4,读、执行),系统调用-创建,实 例,文件描述,在Linux系统中,所有打开的文件都对应一个文件描述符。文件描述符是一个非负整数。当打开一个文件时,内核向进程返回一个文件描述符。文件描述符的范围是0-OPEN_MAX。早期的UNIX版本

14、OPEN_MAX=19,即允许每个进程同时打开20个文件,现在很多系统则将其增加至1024。,系统调用-打开,int open(const char*pathname,int flags)int open(const char*pathname,int flags,mode_t mode)Pathname:要打开的文件名(包含路径,缺省为当前路径)Flags:打开标志,系统调用-打开,Flags 含义O_RDONLY 只读方式打开O_WRONLY 只写方式打开O_RDWR 读写方式打开O_APPEND 追加方式打开O_CREAT 创建一个文件,系统调用-打开,Flags 含义O_NOBLOCK

15、 非阻塞方式打开O_TRUNC 如果文件已经存在,则删除文件的内容O_EXEC 如果使用了O_CREAT,且文件已存在,则报错,系统调用-打开,O_RDONLY、O_WRONLY、O_RDWR三个标志不能同时使用。如果使用了O_CREATE标志,则使用的函数是int open(const char*pathname,int flags,mode_t mode);这时还要指定mode来表示文件的访问权限。,系统调用-打开,实 例,系统调用-关闭,当我们操作完文件以后,需要关闭文件:int close(int fd)Fd:文件描述符,来源?,系统调用-读,int read(int fd,const

16、 void*buf,size_t length)功能:从文件描述符fd所指定的文件中读取length个字节到buf所指向的缓冲区中,返回值为实际读取的字节数。,系统调用-写,int write(int fd,const void*buf,size_t length)功能:把length个字节从buf指向的缓冲区中写到文件描述符fd所指向的文件中,返回值为实际写入的字节数。,系统调用-定位,int lseek(int fd,offset_t offset,int whence)功能:将文件读写指针相对whence移动offset个字节。操作成功时,返回文件指针相对于文件头的位置。,系统调用-定位

17、,whence可使用下述值:SEEK_SET:相对文件开头SEEK_CUR:相对文件读写指针的当前位置SEEK_END:相对文件末尾 offset可取负值,例如下述调用可将文件指针相对当前位置向前移动5个字节:lseek(fd,-5,SEEK_CUR),系统调用-定位,如何利用lseek来计算文件长度?,系统调用-定位,由于lseek函数的返回值为文件指针相对于文件头的位置,因此下列调用的返回值就是文件的长度:lseek(fd,0,SEEK_END),系统调用-访问判断,有时侯我们要判断文件是否可以进行某种操作(读,写等),这个时候我们可以使用access函数。int access(const

18、 char*pathname,int mode)Pathname:文件名称Mode:要判断的属性。可以取以下值或者是他们的组合.R_OK文件可读,W_OK文件可写,X_OK文件可执行,F_OK文件存在。返回值:当我们测试成功时,函数返回0,否则如果一个条件不符时,返回-1。,系统调用-访问判断,例:#includeint main()if(access(“/etc/passwd”,R_OK)=0)printf(“/etc/passwd can be read!n”);,系统调用-属性,文件具有各种属性,除了常见的访问权限以外,文件还有创建时间,大小等属性,文件属性使用 Struct Stat

19、结构描述。,系统调用-属性,struct stat dev_t st_dev;/*设备*/ino_t st_ino;/*节点*/mode_t st_mode;/*模式*/nlink_t st_nlink;/*硬连接*/uid_t st_uid;/*用户ID*/gid_t st_gid;/*组ID*/dev_t st_rdev;/*设备类型*/off_t st_off;/*文件字节数*/unsigned long st_blksize;/*块大小*/unsigned long st_blocks;/*块数*/time_t st_atime;/*最后一次访问时间*/time_t st_mtime;

20、/*最后一次修改时间*/time_t st_ctime;/*最后一次改变时间(指属性)*/;,系统调用-属性,使用最多的属性是st_mode,通过属性我们可以判断给定的文件是一个普通文件还是一个目录,连接等等,可以结合下面几个宏来判断。S_ISLNK(st_mode):是否是一个连接S_ISREG(st_mode):是否是一个常规文件S_ISDIR(st_mode):是否是一个目录S_ISCHR(st_mode):是否是一个字符设备.S_ISBLK(st_mode):是否是一个块设备S_ISFIFO(st_mode):是否是一个FIFO文件S_ISSOCK(st_mode):是否是一个SOCK

21、ET文件,系统调用-属性,如果我们要获取文件的属性,我们可以使用函数:int stat(const char*file_name,struct stat*buf)int fstat(int filedes,struct stat*buf)Stat:判断没有打开的文件Fstat:判断打开的文件,系统调用-文件,综 合 实 例,Linux目录文件操作,路径获取,在编写程序的时候,有时候需要得到当前路径。C库函数提供了getcwd来解决这个问题。char*getcwd(char*buffer,size_t size)我们提供一个size大小的buffer,getcwd会把当前的路径名copy 到bu

22、ffer中.如果buffer太小,函数会返回-1。,路径获取,#includemain()char buf80;getcwd(buf,sizeof(buf);printf(“current working directory:%sn”,buf);,创建,#include int mkdir(char*dir,int mode)功能:创建一个新目录。返回值:0表示成功,-1表述出错。,打开,#include#includeDIR*opendir(const char*name)功能:打开参数name指定的目录返回值:成功则返回DIR*型态的目录流,打开失败则返回NULL。,读取,#include

23、#include struct dirent*readdir(DIR*dir)功能:返回参数dir目录流的下个目录进入点,读取,struct dirent ino_t d_ino;ff_t d_off;signed short int d_reclen;unsigned char d_type;har d_name256;d_ino 此目录进入点的inoded_off 目录文件开头至此目录进入点的位移d_reclen _name的长度,不包含NULL字符d_type d_name 所指的文件类型d_name 文件名,读取位置,#includeoff_ttelldir(DIR*dir)功能:返回

24、dir目录流目前的读取位置。,读取位置,#include#include#includemain()DIR*dir;structdirent*ptr;intoffset;dir=opendir(/etc/rc.d);while(ptr=readdir(dir)!=NULL)offset=telldir(dir);printf(d_name:%soffset:%d n,ptr-d_name,offset);closedir(dir);,定位,#includevoid seekdir(DIR*dir,off_t offset)功能:设置参数dir目录流目前的读取位置,在调用readdir()时便从

25、此新位置开始读取。参数offset 代表距离目录文件开头的偏移量。,定位,#include#include#includemain()DIR*dir;structdirent*ptr;int offset,offset_5,i=0;dir=opendir(/etc/rc.d);while(ptr=readdir(dir)!=NULL)offset=telldir(dir);if(+i=5)offset_5=offset;printf(d_name:%soffset:%d n,ptr-d_name,offset);seekdir(dir.offset_5);printf(Readdir agai

26、n!n);while(ptr=readdir(dir)!=NULL)offset=telldir(dir);printf(d_name:%soffset:%dn,ptr-d_name,offset);closedir(dir);,目录操作,综 合 实 例,文件加锁,对一个文件,一个时刻只能进行一个写操作,所以在写的同时,要对文件加锁,防止别的用户也进行写操作。,文件加锁,一般对要写的文件进行锁定用flock函数#include int flock(int fd,int operation);其中,fd是一个已打开文件的文件描述符;operation表示封锁方式,可以取下列4个值之一:(1)LO

27、CK_SH:共享封锁。多个进程可同时对同一个文件作共享锁定。(2)LOCK_EX:专有封锁。一个文件同时只有一个互斥锁定。(3)LOCK_UN:解除封锁。(4)LOCK_NB:无法建立锁定时,此操作可不被阻断,马上返回进程。返回值:返回0表示成功,若有错误则返回-1,错误代码存于errno。,1.3 I/O模型,在通信过程中,必须明确所采用的I/O方式。在Winsock等通信中,常用的通信方式分为阻塞方式和非阻塞方式。(1)阻塞调用方式是指调用结果返回之前,当前线程会被挂起,函数只有在得到结果之后才会返回。(2)非阻塞和阻塞的概念相对应,指在不能立刻得到结果之前,该函数不会阻塞当前线程,而会立

28、刻返回。,Q:为什么进程间需要通信?A:1、数据传输 一个进程需要将它的数据发送给另一个进程。2、资源共享 多个进程之间共享同样的资源。,1.4 套接字与管道,3、通知事件 一个进程需要向另一个或一组进程发送消息,通知它们发生了某种事件。4、进程控制 有些进程希望完全控制另一个进程的执行(如Debug进程),此时控制进程希望能够拦截另一个进程的所有操作,并能够及时知道它的状态改变。,1.4 套接字与管道,现在linux使用的进程间通信方式包括:1、套接字(socket)2、管道(pipe)和有名管道(FIFO)3、消息队列4、共享内存5、信号量6、信号(signal),1.4 套接字与管道,套

29、接字,Socket Socket是进程间通信(IPC)的方法。Socket接口是主要的TCP/IP网络的API之一,Socket接口定义了许多函数或例程。网络的Socket数据传输是一种特殊的I/O,Socket也是一种文件描述符。,TCP/IP的socket提供下列三种类型套接字。(1)流式套接字(SOCK_STREAM)提供了一个面向连接、可靠的数据传输服务,数据无差错、无重复地发送,且按发送顺序接收。内设流量控制,避免数据流超限;数据被看作是字节流,无长度限制。文件传送协议(FTP)即使用流式套接字。(2)数据报式套接字(SOCK_DGRAM)提供了一个无连接服务。数据包以独立包形式被发

30、送,不提供无错保证,数据可能丢失或重复,并且接收顺序混乱。网络文件系统(NFS)使用数据报式套接字。(3)原始式套接字(SOCK_RAW)该接口允许对较低层协议,如IP、ICMP直接访问。常用于检验新的协议实现或访问现有服务中配置的新设备。,管道通信,Q:什么是管道?A:管道是单向的、先进先出的字节流,它把一个进程的输出和另一个进程的输入连接在一起。写进程在管道的尾部写入数据,读进程从管道的头部读出数据。,管道通信,数据读出后将从管道中移走,其它读进程都不能再读到这些数据。管道提供了简单的流控制机制,进程试图读空管道时,进程将阻塞。同样,管道已经满时,进程再试图向管道写入数据,进程将阻塞。,管

31、道创建,管道包括无名管道和有名管道两种,前者用于父进程和子进程间的通信,后者用于运行于同一台机器上的任意两个进程间的通信。无名管道由pipe()函数创建:int pipe(int filedis2);当一个管道建立时,它会创建两个文件描述符:filedis0 用于读管道,filedis1 用于写管道。,管道通信,管道关闭,关闭管道只需将这两个文件描述符关闭即可,可以使用普通的close函数逐个关闭。,#include#include#include#include int main()int pipe_fd2;if(pipe(pipe_fd)0)printf(pipe create error

32、n);return-1;else printf(pipe create successn);close(pipe_fd0);close(pipe_fd1);,管道通信,管道读写,管道用于不同进程间通信。通常先创建一个管道,再通过fork函数创建一个子进程,该子进程会继承父进程所创建的管道。,注意事项,必须在系统调用fork()前调用pipe(),否则子进程将不会继承文件描述符。管道实例见:pipe_rw.c,实例,pipe_rw.c,命名管道(FIFO),命名管道和无名管道基本相同,但也有不同点:无名管道只能由父子进程使用;但是通过命名管道,不相关的进程也能交换数据。,创建,#include#

33、include int mkfifo(const char*pathname,mode_t mode)Pathname:FIFO文件名Mode:创建标志(见文件操作章节)一旦创建了一个FIFO,就可用open打开它,一般的文件访问函数(close、read、write等)都可用于FIFO。,当打开FIFO时,非阻塞标志(O_NONBLOCK)将对以后的读写产生如下影响:1、没有使用O_NONBLOCK:访问要求无法满足时进程将阻塞。如试图读取空的FIFO,将导致进程阻塞。2、使用O_NONBLOCK:访问要求无法满足时不阻塞,立刻出错返回,errno是ENXIO。,操作,FIFO相关出错信息:

34、EACCES(无存取权限)EEXIST(指定文件已存在)ENAMETOOLONG(路径名太长)ENOENT(包含的目录不存在)ENOSPC(文件系统剩余空间不足)ENOTDIR(文件路径无效)EROFS(指定的文件存在于只读文件系统中),操作,实例,fifo_write.c fifo_read.c,Windows管道,1.管道与邮路 管道是进程用来通信的共享内存区域。管道是进程间数据交流的通道。邮路(mailslot)的功能与管道类似,但它使用数据包广播消息。因此,命名管道最适合用来两个进程间消息传递,邮路则更适合一个进程向多个进程广播消息。匿名管道只能单向传送数据,而命名管道可以双向传送。,

35、Windows管道,2.Windows中管道的使用 管道通常涉及两个进程:客户进程和服务器进程。服务器进程负责创建管道,并且可以创建一个管道的多个实例;客户进程连接到管道。在Windows环境下,匿名管道的创建函数:BOOL CreatePipe()命名管道的创建函数:HANDLE CreateNamePipe()以及其他管道函数。例1-3 命名管道通信的实现(自学了解),1.5 进程与线程,理论:1.5.1 进程概念1.5.2 进程编程实验:进程创建进程等待进程删除,进程定义,进程:通常被定义为一个正在运行的程序的实例,是一个具有一定独立功能的程序在其自身的地址空间中的一次运行活动。,进程,

36、进程由2部分组成:1.内核对象 操作系统用来管理进程的内核对象。内核对象也就是系统用来存放有关进程的统计信息的地方。2.地址空间 地址空间包含所有可执行模块或DLL模块的代码和数据,还包含动态内存分配的空间。比如:线程堆栈和堆分配空间,进程,进程从来不执行任何东西,它只是线程的容器。若要使进程完成某项操作,它必须拥有一个在它环境里运行的线程,此线程负责执行包含在进程的地址空间中的代码。单个进程可能包含若干线程,这些线程都是“同时”执行进程地址空间中的代码。每个进程至少拥有一个线程,来执行地址空间中的代码。当创建一个进程时,系统会自动创建这个进程的第一个线程,此线程称为主线程。此后,主线程再创建

37、其它线程,进程特点,动态性并发性独立性异步性,进程状态,进程控制块 PCB(Process Control Block),存放进程的管理和控制信息的数据结构称为进程控制块。它是进程管理和控制的最重要的数据结构,每一个进程均有一个PCB,在创建进程时,建立PCB,伴随进程运行的全过程,直到进程撤消而撤消。在不同的操作系统中对进程的控制和管理机制不同,PCB中的信息多少也不一样,但PCB中基本信息是一样。,进程ID,进程ID(PID):标识进程的唯一数字父进程的ID(PPID)启动进程的用户ID(UID),进程互斥,进程互斥是指当有若干进程都要使用某一共享资源时,任何时刻最多允许一个进程使用,其他

38、要使用该资源的进程必须等待,直到占用该资源者释放了该资源为止。,临界资源,操作系统中将一次只允许一个进程访问的资源称为临界资源。,临界区,进程中访问临界资源的那段程序代码称为临界区。为实现对临界资源的互斥访问,应保证诸进程互斥地进入各自的临界区。,进程同步,一组并发进程按一定的顺序执行的过程称为进程间的同步。具有同步关系的一组并发进程称为合作进程,合作进程间互相发送的信号称为消息或事件。,进程调度,概念:按一定算法,从一组待运行的进程中选出一个来占有CPU运行。调度方式:抢占式非抢占式,调度算法,先来先服务调度算法短进程优先调度算法高优先级优先调度算法时间片轮转法,死锁,多个进程因竞争资源而形

39、成一种僵局,若无外力作用,这些进程都将永远不能再向前推进。,Linux多进程编程的系统调用,获取ID,#include#include pid_t getpid(void)获取本进程ID。pid_t getppid(void)获取父进程ID。,获取ID,#include#include#include int main(void)printf(PID=%dn,getpid();printf(PPID=%dn,getppid();return 0;,进程创建,#includepid_t fork(void)功能:创建子进程fork的奇妙之处在于它被调用一次,却返回两次,它可能有三种不同的返回值:

40、在父进程中,fork返回新创建的子进程的PID;在子进程中,fork返回0;如果调用失败,fork返回-1给父进程,不生成子进程。,进程创建,#include#inlcudemain()pid_t pid;/*此时仅有一个进程*/pid=fork();/*此时已经有两个进程在同时运行*/if(pid0)printf(error in fork!);else if(pid=0)printf(I am the child process,ID is%dn,getpid();else printf(I am the parent process,ID is%dn,getpid();?执行后的结果?,

41、进程创建,$./fork_testI am the parent process,my process ID is 1991I am the child process,my process ID is 1992在pid=fork()之前,只有一个进程在执行,但在这条语句执行之后,就变成两个进程在执行了,这两个进程的代码部分完全相同,将要执行的下一条语句都是if(pid=0)。两个进程中,原先就存在的那个进程被称作“父进程”,新出现的那个进程被称作“子进程”,父子进程的区别在于进程标识符(PID)不同。,进程创建思考运行结果?,#include#include int main(void)pi

42、d_t pid;int count=0;pid=fork();printf(This is first time,pid=%dn,pid);printf(This is second time,pid=%dn,pid);count+;printf(count=%dn,count);if(pid0)printf(This is parent process,the child has the pid:%dn,pid);else if(!pid)printf(This is the child process.n);else printf(fork failed.n);printf(This is

43、 third time,pid=%dn,pid);printf(This is fouth time,pid=%dn,pid);return 0;,进程创建思考运行结果?,This is first time,pid=0This is second time,pid=0count=1This is the child process.This is third time,pid=0This is fouth time,pid=0This is first time,pid=3512This is second time,pid=3512count=1This is the parent pro

44、cess,the child has pid:3512This is third time,pid=3512This is fouth time,pid=3512问题:为何count+执行了两次,第2次打印count确为1?,进程创建思考运行结果?,父进程的数据空间、堆栈空间都会给子进程一个拷贝,而不是共享这些内存。在子进程中对count进行自加1的操作,但是并没有影响到父进程中的count值,父进程中的count值仍然为0。,进程创建,#include#include pid_t vfork(void)功能:创建子进程。,创建进程,区别:fork要拷贝父进程的数据段;而vfork则不需要完全

45、拷贝父进程的数据段,子进程与父进程共享数据段。2.fork不对父子进程的执行次序进行任何限制;而在vfork调用中,子进程先运行,父进程挂起。,进程创建,#include#include#include main()intcount=1;intchild;printf(Beforecreateson,thefatherscountis:%dn,count);if(!(child=vfork()printf(Thisisson,hispidis:%dandthecountis:%dn,getpid(),+count);exit(1);else printf(Afterson,Thisisfath

46、er,hispidis:%dandthecountis:%d,andthechildis:%dn,getpid(),count,child);,执行程序,exec用被执行的程序替换调用它的程序。区别:fork创建一个新的进程,产生一个新的PID。exec启动一个新程序,替换原有的进程,因此进程的PID不会改变,和调用exec函数的进程一样。,执行程序,#includeint execl(const char*path,const char*arg,.)功能:运行参数path所指定的可执行文件,接下来的参数代表执行该文件时传递过去的argv0、argv1,最后一个参数必须用空指针(NULL)作结

47、束。,执行程序,#includemain()execl(“/bin/ls”,”-al”,”/etc/passwd”,(char*)0);,执行程序,#includeint execlp(const char*file,const char*arg,)功能:从PATH 环境变量所指的目录中查找符合参数file的文件名,找到后便执行该文件,然后将第二个以后的参数当做该文件的argv0、argv1,最后一个参数必须用空指针(NULL)作结束。,执行程序,#includemain()execlp(”ls”,”-al”,”/etc/passwd”,(char*)0);,执行程序,#include int

48、 execv(const char*path,char*const argv)功能:执行参数path所指定的文件,与execl()不同的地方在于execve()只需两个参数,第二个参数利用数组指针来传递给执行文件。,执行程序,#includemain()char*argv=“ls”,”-al”,”/etc/passwd”,(char*);execv(“/bin/ls”,argv);,执行程序,#include int system(const char*string)功能:调用fork()产生子进程,由子进程来调用命令解释器/bin/sh-c string来执行参数string字符串所代表的命

49、令。,执行程序,includemain()system(“ls-al/etc/passwd/etc/shadow”);,等待,#include#includepid_t wait(int*status)功能:进程一旦调用了wait,就立即阻塞自己,直到自己的某个子进程退出,如果没有找到这样一个子进程,wait就会一直阻塞在这里,直到有一个出现为止。,等待,#include#include#include#include main()pid_t pc,pr;pc=fork();if(pc0)/*如果出错*/printf(error ocurred!n);else if(pc=0)/*如果是子进程

50、*/printf(This is child process with pid of%dn,getpid();sleep(10);/*睡眠10秒钟*/else/*如果是父进程*/pr=wait(NULL);/*在这里等待*/printf(I catched a child process with pid of%dn),pr);exit(0);,等待,#include#includepid_t waitpid(pid_t pid,int*status,int options)功能:进程一旦调用了wait,就立即阻塞自己,直到自己的某个子进程退出,如果没有找到这样一个子进程,wait就会一直阻塞

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 生活休闲 > 在线阅读


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号