网站建设得多少钱,河南郑州软件开发公司,wordpress换空间域名,制作网站语言Linux文件系统与设备文件 文章目录 Linux文件系统与设备文件Linux文件操作文件操作系统调用C库文件操作 Linux文件系统Linux文件系统目录结构Linux文件系统与设备驱动file结构体inode结构体file结构体和inode结构体的区别 devfsudev用户空间设备管理sysfs文件系统与Linux设备模…Linux文件系统与设备文件 文章目录 Linux文件系统与设备文件Linux文件操作文件操作系统调用C库文件操作 Linux文件系统Linux文件系统目录结构Linux文件系统与设备驱动file结构体inode结构体file结构体和inode结构体的区别 devfsudev用户空间设备管理sysfs文件系统与Linux设备模型 字符设备和块设备体现了Linux中的一切皆文件的设计思想驱动通过文件操作相关的系统调用和C库函数本质也属于系统调用被访问其次驱动工程师在设备驱动中不可避免会与设备文件系统打交道这也引出了我们需要掌握设备文件系统的相关知识。 Linux文件操作
文件操作系统调用
涉及到创建打开关闭等操作
创建
int creat(const char *filename, mode_t mode)
其中参数filename指的是文件名mode指的是文件的权限它同umask决定了文件的最终权限umask代表了文件在创建时要去除的一些存取权限
int umask(int newmask)
将umask设置为新的mask然后返回旧的umask只影响读写执行的权限
打开
int open(const char *pathname, int flags, mode_t mode);
int open(const char *pathname, int flags);
pathname默认的是当前文件夹的下面
文件的打开标志
标志含义O_RDONLYO_WRONLYO_RDWRrdonlywronly和rdwr这三个标志只能选取其中一个不能同时存在O_APPENDO_CREATO_EXEC如果使用了O_CREAT而且文件已经存在就会发生一个错误O_NOBLOCK以非阻塞的方式打开一个文件O_TRUNC如果文件已经存在则删除文件的内容
如果使用了mode_t表示打开时有文件的访问权限
标志含义S_IRUSR用户可以读S_IWUSRS_IXUSRS_IRGRP组可以读S_IWGRPS_IXGRPS_IROTH其他人可以读S_IWOTHS_IXOTHS_IRWXO其他人可以读写执行S_ISUID设置用户执行IDset UIDS_ISGID设置组执行ID
除了上述宏来表示的产生标志之外我们自己也可以用数字来表示
文件权限共5位从左往右数第一位用户ID、第二位组ID、第三位自己的权限、第四位组权限、第五位其他人的权限
数字表示1执行权限、2写权限、4读权限、0无权限 例如要创建一个用户可读、可写、可执行、但是组没有权限其他人可以读、可以执行的文件并设置用户ID。 open(filename, O_CREAT, 10 705); open(filename, O_CREAT, S_IRWXU|S_IROTH|S_XOTH|S_ISUID);
如果文件打开成功会返回一个文件描述符以后对于文件的所有操作都可以通过对这个文件描述符进行操作来实现。
读写
int read(int fd, const void *buf, size_t length);
buf为缓冲区名称length为缓冲区的大小单位为字节表示在fd中读取length个字节写入buf中返回的是实际读取的字节数。
int write(int fd, const void *buf, size_t length);
表示从buf中读取length字节数写入fd中返回实际写入的字节数
定位lseek
int lseek(int fd, offset_t offset, int whence);
lseek将文件的读写指针相对whence移动了offset个字节返回文件指针相对于文件开发的位置
SEEK_SET相对文件开头SEEK_CUR相对当前位置SEEK_END相对文件末尾
lseek(fd, 0, SEEK_END) 表示文件的大小
也就是文件指针是从wherece的位置处开始移动结果移动了0个位置指针就停在了whence的位置而函数返回值是文件指针相对于文件开头的位置因此这个返回值就是文件的长度。
关闭
int close(int fd);
例如编写一个程序在当前目录下面创建用户可读写文件hello.txt在其中写入“hellosoftware weekly”,关闭该文件再次打开该文件读取其中的内容输出在屏幕上
#include sys/types.h
#include sys/stat.h
#include fcntl.h
#include unistd.h
#include string.h
#include stdio.h#define BUFF_SIZE 100int man()
{int ret;char buff[BUFF_SIZE];int fd open(hello.txt, O_CREAT|O_RDWR, S_IRUSR|S_IWUSR);if(fd){ret write(fd, hello,software weekly, strlen(hello,software weekly));if(ret 0)printf(write failed\n);close(fd);
}else{printf(creat failed\n);
}fd open(hello.txt, O_RDONLY);ret read(fd, buff, sizeof(buff));if(ret){printf(read failed\n);close(fd);
}buff[ret] \0;printf(%s\n, buff);close(fd);
}C库文件操作
创建和打开
FILE *fopen(const char *path, const char *mode);
mode为C库函数打开的标志
标志含义r、rb读r、rb读写w写不存在则创建w、wb读写不存在则创建a追加不存在则创建a、ab读写且追加不存在则创建
b为二进制文件在window下面是有区分的但是Linux下面则没有
读写
int fgetc(FILE *stream);
int fputc(int c, FILE *stream);
char *fgets(char *s, int size, FILE *stream);
int fputs(const char *s, FILE *stream);
size_t fread(void *ptr, size_t size, size_t n, FILE *stream);
size_t fwrite(const void *ptr, size_t size, size_t nmemb,FILE *stream);fread表示从stream流中读取n个字段每个字段大小为size个字节将读取到的数据存到ptr中返回已经读取的字段数。当读取的字段数小于n时可能是在函数调用时出现了错误也可能是读到了文件的末尾。因此要通过调用feof()和ferror()来判断。
另外C库还提供了定位函数
int fseek(FILE *stream, long offset, int whence);
int fgetpos(FILE *stream, fpos_t *pos);
int fsetpos(FILE *stream, const fpos_t *pos);关闭
int fclose(FILE *stream);
例如编写一个程序在当前目录下面创建用户可读写文件hello.txt在其中写入“hello,software weekly”,关闭该文件再次打开该文件读取其中的内容输出在屏幕上
#include stdio.h#define BUFF_SIZE 100
int main()
{char buff[BUFF_SIZE];FILE *fd fopen(hello.txt, w);if (fd){fputs(hello,software weekly, fd);fclose(fd);
}fd fopen(hello.txt, r);if(fd){fgets(buff, sizeof(buff), fd);printf(%s\n, buff); //fgets函数会默认在字符串后面补\0fclose(fd);
}
}
Linux文件系统
Linux文件系统目录结构
linux文件系统目录结构
Linux文件系统与设备驱动
应用程序与文件系统直接的接口是系统调用文件系统与设备文件之间的接口是file_operations结构体成员函数。
由于字符设备的上层没有类似于文件系统所以字符设备的file_operations成员函数就直接由设备驱动提供了
块设备有两种访问方法: 一种是不通过文件系统直接访问裸设备在Linux内核实现了统一的def_blk_fops这一file_operations 类似于”dd if/dev/sdb1 ofsdb1.img”这一指令是不通过文件系统直接访问的驱动设备文件 第二种是通过文件系统访问块设备file_operations的实现则位于文件系统内文件系统会把针对文件的读写转换为针对块设备原始扇区的读写 在设备驱动程序的设计种一般而言会关心file和inode这两个结构体
file结构体
系统中每个打开的文件在内核空间都有一个关联的struct file在内核和驱动源代码中struct file的指针通常被命名为file或者filep
文件结构体struct file中读写模式mode、标志f_flags都是设备驱动关心得内容而私有指针private_data在设备驱动中被广泛使用大多数指向设备驱动自定义以**用于描述设备的结构体**是更高级的文件描述依赖于低层的struct inode数据结构 inode结构体
VFS inode是Linux管理文件系统的最基本的单位也是文件系统连接任何子目录文件的桥梁只与操作系统相关用于保存文件或者目录信息。
表示设备文件的inode结构i_rdev字段包含设备编号。Linux的设备编号分为主设备编号和次设备编号前者为dev_t的高12位后者位dev_t的低20位
unsigned int imajor(struct inode *inode); 获取主设备号主设备号是驱动对应的概念同一类设备一般使用相同的主设备号序号一般从0开始
unsigned int imanor(struct inode *inode); 获取次设备号
查看 /proc/devices 可以获知系统中所注册的设备
file结构体和inode结构体的区别
struct inode和struct file的区别在于inode只关心操作系统找出底层文件结构的内容例如什么设备文件而不去具体的跟踪文件的当前位置和当前模式。struct file是个基本结构实际上持有一个struct inode的指针他代表打开的文件并且提供一组函数他们与底层文件结构执行方法有关
也就是说struct inode只代表内核中的文件而struct file表示实际打开的文件同一个文件被打开时可能有多个文件描述符但他们都指向同一个inode。
devfs
devfs设备文件系统是由Linux 2.4内核出现的使得设备驱动程序能够自主地管理自己的设备文件
可以在程序初始化的时候在/dev目录下创建设备文件卸载设备时将它删除设备驱动程序可以指定设备名、所有者和权限位不再需要为设备驱动程序分配主设备号以及处理次设备号在程序中可以直接给 register_chrdev()传递0主设备号以获得可用的主设备号并在 devfs_register()中指定次设备号
udev用户空间设备管理
udev是在Linux 2.6的时候被引入与devfs不同的是就像谈恋爱udev系统可以使得用户在上层自由选择和谁谈恋爱而不能在内核空间限制和谁谈恋爱。对于devfs而言第一个相亲女孩被命名为/dev/girl0第二个相亲女孩被命名为/dev/girl1。而在用户空间实现的udev则可以不管你中意的女孩是第几个只要符合要求都是/dev/mygirl。udev完全工作在用户态利用设备的热插拔事件来工作详细的设备信息会由内核通过netlink套接字发送出来发出的事情叫uevent。那冷插拔事件怎么办呢设备当主机开机时就已经存在了Linux内核提供了sysfs下面的一个uevent节点往该节点写一个”add”具体怎么写我也不是很懂导致内核重新发送netlink之后udev就可以收到冷插拔的netlink消息了对于devfs当一个并不存在的/dev节点被访问时系统会自动加载相对应的设备驱动而udev却不是这样是在产生热插拔事件时才会加载相应的驱动并且创建的对应节点
sysfs文件系统与Linux设备模型
udev和sysfs都是Linux系统的一部分但它们有不同的功能和用途。sysfs是一个虚拟文件系统用于从用户空间访问内核对象的属性。它将内核对象的属性表示为文件和目录使得用户空间的程序能够通过标准的文件系统接口查询和更改内核对象的属性。包括展示设备驱动模型中各组件的层次关系。
在/sys/目录下的顶级目录
block包含所有的块设备devices包含系统所有的设备bus包含所有的总线类型class包含系统中的设备类型
他们实际上都会被认为是kobject的派生类一个kobject对应sysfs中的一个目录。
在/sys/bus/pci的目录下又会出现devices和drivers而这个devices目录下的文件是对/sys/devices下的文件的符号链接
与此不同udev是一个设备管理器它管理/dev目录下的设备节点。当内核检测到新设备时它将发送一个ueventudev将接收到这个事件并对其进行处理。这可能包括加载设备驱动创建或删除设备节点甚至更改设备的权限和所有权。udev的工作依赖于sysfs因为它使用sysfs提供的信息来确定如何处理设备。
总的来说sysfs是一个提供有关内核对象的信息的接口而udev则使用这些信息来管理设备。就好比udev是做饭的方法而sys是菜和米饭 在Linux内核中分别使用bus_type、device_driver和device来描述总线、驱动和设备这三个结构体定义在include/linux/device.h中 device_driver和device分别代表驱动和设备他们都会挂载在总线上面因此结构体中也都包含struct bus_type指针驱动和设备注册的时候不需要都存在注册设备时不需要对应的驱动被注册注册驱动时不需要对应的设备被注册而都注册之后又如何连接起来呢通过bus_type结构体的match()成员将两者捆绑在一起一旦捆绑成功bus_driver的probe()就被执行驱动、设备、总线的attribute都会落实为sys中的一个文件会伴随着show()和store()这两个函数进行读写操作sysfs中的目录来源于device、device_driver、bus_type而目录中的文件就来源于attribute定义了一些快捷方式以方便attribute的创建工作 #define DRIVER_ATTR(_name, _mode, _show, _store) \struct driver_attribute driver_attr_##_name __ATTR(_name, _
mode, _show, _store)
#define DRIVER_ATTR_RW(_name) \struct driver_attribute driver_attr_##_name __ATTR_RW(_name)
#define DRIVER_ATTR_RO(_name) \struct driver_attribute driver_attr_##_name __ATTR_RO(_name)
#define DRIVER_ATTR_WO(_name) \struct driver_attribute driver_attr_##_name __ATTR_WO(_name)#define BUS_ATTR(_name, _mode, _show, _store) \struct bus_attribute bus_attr_##_name __ATTR(_name, _mode, _show, _
store)
#define BUS_ATTR_RW(_name) \struct bus_attribute bus_attr_##_name __ATTR_RW(_name)
#define BUS_ATTR_RO(_name) \struct bus_attribute bus_attr_##_name __ATTR_RO(_name)#define DEVICE_ATTR(_name, _mode, _show, _store) \struct device_attribute dev_attr_##_name __ATTR(_name, _mode, _show, _store)
#define DEVICE_ATTR_RW(_name) \struct device_attribute dev_attr_##_name __ATTR_RW(_name)
#define DEVICE_ATTR_RO(_name) \struct device_attribute dev_attr_##_name __ATTR_RO(_name)
#define DEVICE_ATTR_WO(_name) \struct device_attribute dev_attr_##_name __ATTR_WO(_name)
#define DEVICE_ULONG_ATTR(_name, _mode, _var) \struct dev_ext_attribute dev_attr_##_name \{ __ATTR(_name, _mode, device_show_ulong, device_store_ulong), (_var) }
#define DEVICE_INT_ATTR(_name, _mode, _var) \struct dev_ext_attribute dev_attr_##_name \{ __ATTR(_name, _mode, device_show_int, device_store_int), (_var) }
#define DEVICE_BOOL_ATTR(_name, _mode, _var) \struct dev_ext_attribute dev_attr_##_name \{ __ATTR(_name, _mode, device_show_bool, device_store_bool), (_var) }
#define DEVICE_ATTR_IGNORE_LOCKDEP(_name, _mode, _show, _store) \struct device_attribute dev_attr_##_name \__ATTR_IGNORE_LOCKDEP(_name, _mode, _show, _store)撰写不易留下您的关注和点赞我们一起进步