Linux 文件系统与设备文件系统 2008-06-19 15:16 由于字符设备和块设备都很好地体现了“一切都是文件”的设计思想,掌握Linux文件系统、设备文件系统的知识非常重要。 首先,设备驱动最终通过操作系统的文件系统调用或C库函数(本质也基于系统调用)被访问。 其次,驱动工程师在设备驱动中不可避免地会与设备文件系统打交道,如Linux 2.4内核的devfs文件系统和Linux 2.6内核的基于sysfs的udev文件系统。 1节讲解了通过Linux API和C库函数的用户空间进行Linux文件操作的编程方法。 2节分析了Linux文件系统的目录结构,简单介绍了Linux内核中文件系统的实现,并给出了文件系统与设备驱动的关系。 3节和4节分别讲解Linux 2.4内核的devfs和Linux 2.6内核所采用的udev设备文件系统,并分析了两者的区别。 1.1 Linux文件操作 1.1.1 文件操作的相关系统调用 Linux 的文件操作系统调用涉及创建、打开、读写和关闭文件。 1. 创建 int create (const char *filename , mode_t mode); 参数mode指定新建文件的存取权限,它同umask一起决定文件的最终权限(mode&umask),其中umask代表了文件在创建时需要去掉的一些存取权限。umask可通过系统调用umask()来改变,如下所示: int umask (int newmask); 该调用将umask设置为newmask,然后返回旧的umask,它只影响读、写和执行权限。 2 . 打开 int open(const char *pathname , int flags); int open (const char *pathname, int flags, mode_t mode ); open()函数有两个形式,其中pathname是我们要打开的文件名(包含路径名称,默认时认为在当前路径下面),flags可以是如下表所示的一个值或几个值得组合。 表1.1 文件打开标志 标志 含义 O_RDONLY 以只读的方式打开文件 O_WRONLY 以只写的方式打开文件 O_RDWR 以读写的方式打开文件 O_APPEND 以追加的方式打开文件 O_CREAT 创建一个文件 O_EXEC 如果使用了O_CREAT而且文件已经存在,就会发生一个错误 O_NOBLOCK 以非阻塞的方式打开一个文件 O_TRUNC 如果文件已经存在,則删除文件的内容 O_RDONLY、O_WRONLY、O_RDWR这3个标志只能使用任意的一个。 如果使用了O_CREATE标志,則使用的函数是int open(const char *pathname ,int flags,mode_t mode);这个时候我们还有指定mode标志,用来表示文件的访问权限。Mode可以是表1.2 所示值得组合。 表1.2 文件访问权限 标志 含义 S_IRUSR 用户可以读 S_IWUSR 用户可以写 S_IXUSR 用户可以执行 S_IRWXU 用户可以读、写、执行 S_IRGRP 组可以读 S_IWGRP 组可以写 S_IXGRP 组可以执行 S_IRWXG 组可以读、写、执行 S_IROTH 其他人可以读 S_IWOTH 其他人可以写 S_IXOTH 其他人可以执行 S_IRWXO 其他人可以读、写、执行 S_ISUID 设置用户的执行ID S_ISGID 设置组的执行ID 除 了可以通过上述宏进行“或”逻辑产生标志外,我们也可以自己用数字来表示,Linux总共用5个数字来表示文件的各种权限:第一位表示设置用户ID;第二 位表示设置组ID;第三位表示用户自己的权限位;第四位表示组的权限;第五位表示其他人的权限。每个数字可以取1(执行权限)、2(写权限)、4(读权 限)、0(无)或者是这些值得和。 例 如,如果要创建一个用户可读、可写、可执行,但是组没有权限,其他人可以读、可以执行的文件,并设置用户ID位。那么,应该使用的模式是1(设置用户 ID)、0(不设置组ID)、7(1 2 4,读、写、执行)、0(没有权限)、5(1 4,读、执行)即10705,如下所示: Open(“test”,O_CREAT, 10705); 上述语句等价于: open(“test”,O_CREAT, S_IRWXU | S_IROTH | S_IXOTH | S_ISUID ); 如果文件打开成功,open函数会返回一个文件描述符,如果对该文件的所有操作就可以通过对这个文件描述符进行操作来实现。 3. 读写 在文件打开以后,我们才可以对文件进行读写,linux系统中提供文件读写的系统调用是read、write函数,如下所示: int read (int fd ,const void *buf,size_t length); int write (int fd ,const void *buf,size_t length); 其中参数buf为:指向缓冲区的指针,length为缓冲区的大小(以字节为单位)。函数read()实现从文件描述符fd所指定的文件中读取length个字节到buf 所指向的缓冲区中,返回值为实际读取的字节数。函数write实现把length个字节从buf指向的缓冲区中写道文件描述符fd指向的文件中,返回值为实际写入的字节数。 以O_CREAT为标志的open函数实际上实现了文件创建的功能,因此,下面的函数等同creat()函数: int open(pathname , O_CREAT | O_WRONLY | O_TRUNC ,mode); 4.定位 对于随机文件,我们可以随机地指定位置读写,使用如下函数进行定位: int lseek(int fd, offset_t offset, int whence); lseek()将文件读写指针相对whence移动offset个字节。操作成功时,返回文件指针相对于文件头的位置。参数whence可以使用如下值。 SEEK_SET :相对文件开头。 SEEK_CUR :相对文件读写指针的当前位置。 SEEK_END :相对文件末尾。 Offset 可取负值,例如如下述调用可将文件指针相对当前位置向前移动5个字节。 lseek(fd,-5,SEEK_CUR); 由于lseek函数的返回值为文件指针相对于文件头的位置,因此下列调用的返回值就是文件的长度。 lseek (fd,0,SEEK_END); |
|小黑屋|最新主题|手机版|微赢网络技术论坛 ( 苏ICP备08020429号 )
GMT+8, 2024-9-29 13:21 , Processed in 0.186998 second(s), 12 queries , Gzip On, MemCache On.
Powered by Discuz! X3.5
© 2001-2023 Discuz! Team.