您好,欢迎访问三七文档
文件系统【要求】掌握锁的结构和操作掌握如何对文件进行加锁、解锁学会如何协调不同进程对同一文件的互斥操作【内容】必做:文件锁的测试选做:创建一个带有空洞的文件理解文件中空洞出现的原因掌握lseek函数的用法文件系统简介在linux系统中使用的是ext4文件系统,这种文件系统将它所占有的设备的逻辑分区分成了数据块组,每个块组都包含一些有关整个文件系统的信息及存放真正的文件和目录的数据块。具体来说每个块组都包括引导块、超级块、块组中文件inode表和数据块。引导块(bootblock)中包含了引导信息,硬件从引导设备读入引导块到内存,开始执行其代码来进行操作系统本身的加载。超级块(superblock)中存储着描述文件系统的大小和特性的基本信息,管理员可以使用其中的信息来使用和维护文件系统。文件inode表是文件系统维护的一个索引节点的数组。每一个表项为一个128字节的inode结构,记录了有关该文件的所有信息,包括类型、大小、存取权限、指向存储位置的指针等。文件系统用目录将内部文件按照逻辑层次结构组织成树形结构。而文件系统所在的分区的数据块组包含了文件系统的各种详细信息。用户可以通过目录来查找到相应的具体文件名称,继而找到文件的i节点号,因为一个目录中仅仅记录了文件名和相对应的inode号。这样用户就可以通过索引值(inode号)在全局的i节点表中找到记录在inode结构中的有关该文件的所有信息。linux文件系统linux文件系统引导块超级块i表数据块目录块数据块目录块数据块I节点I节点I节点I节点号文件名I节点号文件名文件在linux中,对文件的定义是不包含任何结构的字符流。也就是说,文件中字符与字符之间除了同属一个文件之外,没有其它关系。对字符之间关系的建立和解释是由使用该文件的应用程序来完成的。一个文件自身的属性都存在一个称为stat的结构中,这些属性包括:文件类型、存取模式、i节点号、文件大小等。一个文件的状态信息是用如下的一个数据结构来表示的:structstat{dev_tst_dev;//设备号(文件系统)ino_tst_ino;//节点号mode_tst_mode;//文件类型和存取许可位nlink_tst_nlink;//链接的个数uid_tst_uid;//文件所有者owner的UIDgid_tst_gid;//文件所有者owner的GIDdev_tst_rdev;//设备类型off_tst_size;//文件总的大小,以byte为单位blksize_tst_blksize;//文件系统I/O的块大小blkcnt_tst_blocks;//已分配的数据块(以512byte为单位)的数目……}所需函数intlstat(constchar*file_name,structstat*buf)file_name是文件名,buf为一个数据结构,记录文件的相关信息执行成功则返回0,失败返回-1获取文件的状态信息文件类型普通文件:用-标示,比如-rwxr--r--,rwx前面的-表明这个是普通文件。目录文件:用d标示,比如drwx------目录也是一个文件。块设备文件:用b标示,表示硬件设备,可以在/dev目录访问这些设备,包含磁盘驱动光盘驱动这类存储的。字符设备文件:用c标示,也表示硬件设备,数据是以字节流发送的,这些设备包括终端设备和串口设备。命名管道文件:用p标示,管道也是一个文件,作为数据管道方便程序之间的通信。套接字文件:用s标示,套接字是方便进程之间通信的特殊文件。与管道不同的是,套接字能促使通过网络连接的不同计算机的进程之间进行通信。符号链接:指向另一个文件的路径名,而非另一个文件的具体内容。实验一(选作):获取文件的状态信息#includesys/types.h#includesys/stat.h#includeunistd.h#includestdlib.h#includestdio.hintmain(intargc,char*argv[]){inti;char*ptr;structstatfilestat;for(i=1;iargc;i++){printf(%s:,argv[i]);if(lstat(argv[i],&filestat)0){printf(lstaterror\n);continue;}if(S_ISREG(filestat.st_mode))ptr=regular;elseif(S_ISDIR(filestat.st_mode))ptr=directory;elseif(S_ISCHR(filestat.st_mode))ptr=characterspecial;elseif(S_ISBLK(filestat.st_mode))ptr=blockspecial;elseif(S_ISFIFO(filestat.st_mode))//先入先出命名管道ptr=fifo;elseif(S_ISLNK(filestat.st_mode))ptr=symboliclink;elseif(S_ISSOCK(filestat.st_mode))ptr=socket;elseptr=unknownmode;printf(%s\n,ptr);}exit(0);}文件基本操作命令open函数:打开一个文件intopen(constchar*pathname,intflags);intopen(constchar*pathname,intflags,mode_tmode);返回值:返回打开的文件句柄,-1打开失败参数pathname指向欲打开的文件路径字符串,既可以是相对路径也可以是绝对路径,flags表示打开此文件的方式,mode指明了对此文件设定存取权限。close函数:关闭一个文件intclose(intfd);当使用完文件后若已不再需要则可使用close()关闭该文件,而close()会让数据写回磁盘,并释放该文件所占用的资源。参数fd为先前由open()或creat()所返回的文件描述符(filedescriptor)。creat函数:创建一个新文件intcreat(constchar*pathname,mode_tmode);creat函数用来创建一个新文件,文件名由参数pathname来指定,同时设置该文件的存取权限。creat()相当于使用下列的调用方式调用open(constchar*pathname,O_WRONLY|O_CREAT|O_TRUNC);lseek函数:移动文件的读写位置off_tlseek(intfildes,off_toffset,intwhence);每一个已打开的文件都有一个读写位置,当新打开文件时通常其读写位置是指向文件开头,若是以附加的方式打开文件(如O_APPEND),则读写位置会指向文件尾。lseek()是用来控制该文件的读写位置。参数fildes为已打开的文件描述符,参数offset为根据参数whence来移动读写位置的位移量。文件基本操作命令read函数:从已打开的文件中读取数据intread(intfd,void*buf,size_tcount);read()函数会从参数fd所指的文件中传送count个字节的数据到buf指针所指的内存中。若参数count为0,则read()不会有作用并返回0。返回值为实际读取到的字节数,如果返回0,表示已到达文件尾或是无可读取的数据,此外文件读写位置会随读取到的字节移动。write函数:将数据写入已打开的文件中intwrite(intfd,constvoid*buf,size_tcount);write()函数会从参数buf所指的内存中写入count个字节到参数fd所指的文件内。当然,文件读写位置也会随之移动。文件基本操作命令dup函数:复制文件描述符intdup(intoldfd);dup()用来复制参数oldfd所指的文件描述符,并返回当前进程可用描述符中的最小值。此后新的文件描述符和参数oldfd指的是同一个文件,共享所有的锁、读写位置和各项权限或标志。通过其中一个文件描述符对文件所作的修改将影响到通过另一个描述符对文件的访问结果。flock函数:对文件加锁解锁intflock(intfd,intoperation);flock()函数会依参数operation所指定的方式对参数fd所指的文件做各种加锁或解锁操作。此函数只能锁定整个文件,无法锁定文件的某一区域。单一文件无法同时建立共享锁定和互斥锁定操作,而当使用dup()或fork()时新的文件描述符不会继承此种锁定。文件基本操作命令fd标志fd0fd2fd1文件状态标志当前文件位移量V节点指针V节点信息I节点信息当前文件长度文件状态标志当前文件位移量V节点指针fd标志fd0fd1fd2进程表项文件表V节点表对一个文件进行open操作后,返回一个文件描述符,进程在已打开文件描述符表中增加一个表项。若是对已打开的文件执行open操作,则此时已打开文件表表项中的指向文件v节点表项的指针将链接到已打开的文件的v节点上。此时,对文件的修改将影响到链接到该文件上的所有描述符的访问,但每个文件描述符有各自独立的文件位移量,不受其它影响。实验二(选做)使用open函数来打开同一文件,测试是否共享当前文件位移量:#includesys/types.h#includeunistd.h#includestdlib.h#includefcntl.hintmain(){intfd1,fd2;charbuf[]=abcdefgh;chartemp[4];fd1=open(tempfile,O_RDWR|O_CREAT|O_TRUNC);if(fd10){printf(cannotopenfile\n);exit(EXIT_FAILURE);}if(write(fd1,buf,8)!=8){printf(cannotwritetofile\n);exit(EXIT_FAILURE);}elseprintf(write:%s\n,buf);fd2=open(tempfile,O_RDWR);if(fd20){printf(cannotopentempfile\n);exit(EXIT_FAILURE);}lseek(fd1,0,SEEK_SET);if(read(fd1,temp,4)!=4){printf(cannotreadfromfd1\n);exit(EXIT_FAILURE);}elseprintf(fd1:%s,temp);if(read(fd2,temp,4)!=4){printf(cannotreadfromfd2\n);exit(EXIT_FAILURE);}elseprintf(fd2:%s,temp);close(fd1);close(fd2);return0;}文件锁•在有多个进程并发执行的情况下,若多个进程同时对同一文件进行写操作,则会导致最后一个进程的执行结果覆盖了以前进程所作的修改,从而产生非预期结果。在linux系统中,fcntl函数向用户提供了对文件加锁、解锁以保证对同一文件或文件内的某一区域的互斥操作。这取决于锁的设定。•进程框架结构:打开一个新文件,再创建一个子进程。父子进程通过fcntl函数进行文件级的加锁,来进行对该文件互斥的访问。flock锁结构为:structflock{shortl_type;//锁的类型shortl_whence;//决定l_start的起点off_tl_start;//要加锁或解锁区域//的起始位置,相对位移量off_tl_len;//区域长度pid_tl_pid;//执行加锁的进程,//F_GETLK时有用}加锁的基本规则为:多个进程可以对同一区域加读锁,但同一时间只能有一个进程对同一区域加写锁。文件锁实验三(必做)文件锁测试#includesys/types.h#includefcntl.h#includeunistd.h#includestd
本文标题:93文件系统
链接地址:https://www.777doc.com/doc-4029577 .html