自适应和响应式网站佛山微信网站建设

当前位置: 首页 > news >正文

自适应和响应式网站,佛山微信网站建设,公司网站域名cn和com,手机软件编程概述 1.当我们运行类似于“dd if/dev/sdb1ofsdb1.img”的命令把整个/dev/sdb1裸分区复制到sdb1.img的时候#xff0c;内核走的是def_blk_fops这个file_operations 2.另外一种方法是通过文件系统来访问块设备#xff0c;file_operations的实现则位于文件系统内#xff0c;文…概述 1.当我们运行类似于“dd if/dev/sdb1ofsdb1.img”的命令把整个/dev/sdb1裸分区复制到sdb1.img的时候内核走的是def_blk_fops这个file_operations 2.另外一种方法是通过文件系统来访问块设备file_operations的实现则位于文件系统内文件系统会把针对文件的读写转换为针对块设备原始扇区的读写。ext2、fat、Btrfs等文件系统中会实现针对VFS的file_operations成员函数设备驱动层将看不到file_operations的存在 块设备节点文件 如 /dev/sdb1直接对应于磁盘分区或整个磁盘。这些设备文件由内核的块设备层直接管理使用 def_blk_fops 文件操作集在open前因为mknod调用的init_special_inode初始化节点的时候指定了inode-i_fop def_blk_fops; mknoddo_mknodatvfs_mknodshmem_mknodshmem_get_inodeinit_special_inode void init_special_inode(struct inode inode, umode_t mode, dev_t rdev) {inode-i_mode mode;if (S_ISCHR(mode)) {inode-i_fop def_chr_fops;inode-i_rdev rdev;} else if (S_ISBLK(mode)) {if (IS_ENABLED(CONFIG_BLOCK))inode-i_fop def_blk_fops;inode-i_rdev rdev;} else if (S_ISFIFO(mode))inode-i_fop pipefifo_fops;else if (S_ISSOCK(mode)); / leave it no_open_fops */elseprintk(KERN_DEBUG init_special_inode: bogus i_mode (%o) for inode %s:%lu\n, mode, inode-i_sb-s_id,inode-i_ino); } 文件系统文件 /path/to/file位于文件系统中由文件系统驱动程序如 ubifs管理inode创建的时候赋予特定的文件操作集如 ubifs_file_operations如下述会通过”inode-i_fop ubifs_file_operations;“给inode赋予特定的文件操作函数 ubifs_new_inode struct inode *ubifs_new_inode(struct ubifs_info *c, struct inode *dir,umode_t mode) {int err;struct inode *inode;struct ubifs_inode ui;bool encrypted false;if (ubifs_crypt_is_encrypted(dir)) {err fscrypt_get_encryption_info(dir);if (err) {ubifs_err(c, fscrypt_get_encryption_info failed: %i, err);return ERR_PTR(err);}if (!fscrypt_has_encryption_key(dir))return ERR_PTR(-EPERM);encrypted true;}inode new_inode(c-vfs_sb);ui ubifs_inode(inode);if (!inode)return ERR_PTR(-ENOMEM);/** Set S_NOCMTIME to prevent VFS form updating [mc]time of inodes and marking them dirty in file write path (see file_update_time()).* UBIFS has to fully control clean - dirty transitions of inodes* to make budgeting work./inode-i_flags | S_NOCMTIME;inode_init_owner(inode, dir, mode);inode-i_mtime inode-i_atime inode-i_ctime current_time(inode);inode-i_mapping-nrpages 0;switch (mode S_IFMT) {case S_IFREG:inode-i_mapping-a_ops ubifs_file_address_operations;inode-i_op ubifs_file_inode_operations;inode-i_fop ubifs_file_operations;break;case S_IFDIR:inode-i_op ubifs_dir_inode_operations;inode-i_fop ubifs_dir_operations;inode-i_size ui-ui_size UBIFS_INO_NODE_SZ;break;case S_IFLNK:inode-i_op ubifs_symlink_inode_operations;break;case S_IFSOCK:case S_IFIFO:case S_IFBLK:case S_IFCHR:inode-i_op ubifs_file_inode_operations;encrypted false;break;default:BUG();}ui-flags inherit_flags(dir, mode);ubifs_set_inode_flags(inode);if (S_ISREG(mode))ui-compr_type c-default_compr;elseui-compr_type UBIFS_COMPR_NONE;ui-synced_i_size 0;spin_lock(c-cnt_lock);/ Inode number overflow is currently not supported /if (c-highest_inum INUM_WARN_WATERMARK) {if (c-highest_inum INUM_WATERMARK) {spin_unlock(c-cnt_lock);ubifs_err(c, out of inode numbers);make_bad_inode(inode);iput(inode);return ERR_PTR(-EINVAL);}ubifs_warn(c, running out of inode numbers (current %lu, max %u),(unsigned long)c-highest_inum, INUM_WATERMARK);}inode-i_ino c-highest_inum;/** The creation sequence number remains with this inode for its lifetime. All nodes for this inode have a greater sequence number,* and so it is possible to distinguish obsolete nodes belonging to a* previous incarnation of the same inode number - for example, for the* purpose of rebuilding the index.*/ui-creat_sqnum c-max_sqnum;spin_unlock(c-cnt_lock);if (encrypted) {err fscrypt_inherit_context(dir, inode, encrypted, true);if (err) {ubifs_err(c, fscrypt_inherit_context failed: %i, err);make_bad_inode(inode);iput(inode);return ERR_PTR(err);}}return inode; } MTD 嵌入式系统最常用的qspi-flash一般作为MTD设备在其上又使用UBIFS来减少闪存的磨损 mount 比如mount文件系统的时候会挂载文件系统到一个根目录这个目录也会通过ubifs_new_inode来创建一个inodemount流程如下 diff –git a/fs/ubifs/dir.c b/fs/ubifs/dir.c index 38fe20f6e..1239fad37 100644 — a/fs/ubifs/dir.cb/fs/ubifs/dir.c-90,7 90,11 struct inode *ubifs_new_inode(struct ubifs_info *c, const struct inode *dir,{struct inode *inode;struct ubifs_inode *ui; -static bool once true;if(once){dump_stack();once false;}inode new_inode(c-vfs_sb);ui ubifs_inode(inode);if (!inode)[ 4.181047] c00198e9 from c0017e5f [ 4.205935] c0017e5f from c00b289f [ 4.242626] c00b289f from c00b2c69 [ 4.251746] c00b2c69 from c00776f7 [ 4.276054] c00776f7 from c00d6c1d [ 4.284503] c00d6c1d from c00d5dc3 [ 4.310915] c00d5dc3 from c00d60b7 [ 4.320431] c00d60b7 from c00732d5 [ 4.335254] c00732d5 from c00738a1 [ 4.343245] c00738a1 from c0081ea3 [ 4.352334] c0081ea3 from c00832cd [ 4.362857] c00832cd from c00833b9 [ 4.372007] c00833b9 from c0009081 创建文件 应用层通过touch命令或者create或者open函数调用创建文件时本质open系统调用带O_CREAT的flag来执行创建的操作 SYSCALL_DEFINE2(creat, const char __user *, pathname, umode_t, mode) {return sys_open(pathname, O_CREAT | O_WRONLY | O_TRUNC, mode); } SYSCALL_DEFINE3(open, const char __user *, filename, int, flags, umode_t, mode) {if (force_o_largefile())flags | O_LARGEFILE;return do_sys_open(AT_FDCWD, filename, flags, mode); } open具体获取inode的具体流程如下 do_sys_opendo_filp_openpath_openat static struct file *path_openat(struct nameidata *nd,const struct open_flags *op, unsigned flags) {const char *s;struct file *file;int opened 0;int error;file get_empty_filp();if (IS_ERR(file))return file;file-f_flags op-open_flag;if (unlikely(file-f_flags __O_TMPFILE)) { /处理临时文件/error do_tmpfile(nd, flags, op, file, opened);goto out2;}if (unlikely(file-f_flags O_PATH)) { /打开一个文件或目录的路径但不进行实际的读写操作/error do_o_path(nd, flags, file);if (!error)opened | FILE_OPENED;goto out2;}s path_init(nd, flags); /初始化路径/if (IS_ERR(s)) {put_filp(file);return ERR_CAST(s);}while (!(error link_path_walk(s, nd)) /* 获取不同文件系统的inode的具体实现*/(error do_last(nd, file, op, opened)) 0) { /创建或打开文件/nd-flags ~(LOOKUP_OPEN|LOOKUP_CREATE|LOOKUP_EXCL);s trailing_symlink(nd);if (IS_ERR(s)) {error PTR_ERR(s);break;}}terminate_walk(nd); out2:if (!(opened FILE_OPENED)) {BUG_ON(!error);put_filp(file);}if (unlikely(error)) {if (error -EOPENSTALE) {if (flags LOOKUP_RCU)error -ECHILD;elseerror -ESTALE;}file ERR_PTR(error);}return file; } 获取inode link_path_walk最终调用到ubiffs_iget来获取inode 通过fast和slow两种方式来查找或者创建inode并初始化inodef的i_fopsinode-i_fop ubifs_file_operations; 对不同文件属性赋值不同操作函数 link_path_walkwalk_componentlookup_fast //用缓存中的 dentry 来避免不必要的磁盘访问从而提高路径解析的效率lookup_slow //它在缓存中找不到匹配的 dentry 时被调用需要通过文件系统的特定方法来查找或创建 dentry 和 inodeinode-i_op-lookup(inode, dentry, flags); ubifs_lookupubifs_igetstruct inode *ubifs_iget(struct super_block *sb, unsigned long inum) {int err;union ubifs_key key;struct ubifs_ino_node *ino;struct ubifs_info *c sb-s_fs_info;struct inode *inode;struct ubifs_inode *ui;dbg_gen(inode %lu, inum);inode iget_locked(sb, inum);if (!inode)return ERR_PTR(-ENOMEM);if (!(inode-i_state I_NEW))return inode;ui ubifs_inode(inode);ino kmalloc(UBIFS_MAX_INO_NODE_SZ, GFP_NOFS);if (!ino) {err -ENOMEM;goto out;}ino_key_init(c, key, inode-i_ino);err ubifs_tnc_lookup(c, key, ino);if (err)goto out_ino;inode-i_flags | S_NOCMTIME; #ifndef CONFIG_UBIFS_ATIME_SUPPORTinode-i_flags | S_NOATIME; #endifset_nlink(inode, le32_to_cpu(ino-nlink));i_uid_write(inode, le32_to_cpu(ino-uid));i_gid_write(inode, le32_to_cpu(ino-gid));inode-i_atime.tv_sec (int64_t)le64_to_cpu(ino-atime_sec);inode-i_atime.tv_nsec le32_to_cpu(ino-atime_nsec);inode-i_mtime.tv_sec (int64_t)le64_to_cpu(ino-mtime_sec);inode-i_mtime.tv_nsec le32_to_cpu(ino-mtime_nsec);inode-i_ctime.tv_sec (int64_t)le64_to_cpu(ino-ctime_sec);inode-i_ctime.tv_nsec le32_to_cpu(ino-ctime_nsec);inode-i_mode le32_to_cpu(ino-mode);inode-i_size le64_to_cpu(ino-size);ui-data_len le32_to_cpu(ino-data_len);ui-flags le32_to_cpu(ino-flags);ui-compr_type le16_to_cpu(ino-compr_type);ui-creat_sqnum le64_to_cpu(ino-creat_sqnum);ui-xattr_cnt le32_to_cpu(ino-xattr_cnt);ui-xattr_size le32_to_cpu(ino-xattr_size);ui-xattr_names le32_to_cpu(ino-xattr_names);ui-synced_i_size ui-ui_size inode-i_size;ui-xattr (ui-flags UBIFS_XATTR_FL) ? 1 : 0;err validate_inode(c, inode);if (err)goto out_invalid;switch (inode-i_mode S_IFMT) {case S_IFREG:inode-i_mapping-a_ops ubifs_file_address_operations;inode-i_op ubifs_file_inode_operations;inode-i_fop ubifs_file_operations;if (ui-xattr) {ui-data kmalloc(ui-data_len 1, GFP_NOFS);if (!ui-data) {err -ENOMEM;goto out_ino;}memcpy(ui-data, ino-data, ui-data_len);((char *)ui-data)[ui-data_len] \0;} else if (ui-data_len ! 0) {err 10;goto out_invalid;}break;case S_IFDIR:inode-i_op ubifs_dir_inode_operations;inode-i_fop ubifs_dir_operations;if (ui-data_len ! 0) {err 11;goto out_invalid;}break;case S_IFLNK:inode-i_op ubifs_symlink_inode_operations;if (ui-data_len 0 || ui-data_len UBIFS_MAX_INO_DATA) {err 12;goto out_invalid;}ui-data kmalloc(ui-data_len 1, GFP_NOFS);if (!ui-data) {err -ENOMEM;goto out_ino;}memcpy(ui-data, ino-data, ui-data_len);((char *)ui-data)[ui-data_len] \0;break;case S_IFBLK:case S_IFCHR:{dev_t rdev;union ubifs_dev_desc *dev;ui-data kmalloc(sizeof(union ubifs_dev_desc), GFP_NOFS);if (!ui-data) {err -ENOMEM;goto out_ino;}dev (union ubifs_dev_desc *)ino-data;if (ui-data_len sizeof(dev-new))rdev new_decode_dev(le32_to_cpu(dev-new));else if (ui-data_len sizeof(dev-huge))rdev huge_decode_dev(le64_to_cpu(dev-huge));else {err 13;goto out_invalid;}memcpy(ui-data, ino-data, ui-data_len);inode-i_op ubifs_file_inode_operations;init_special_inode(inode, inode-i_mode, rdev);break;}case S_IFSOCK:case S_IFIFO:inode-i_op ubifs_file_inode_operations;init_special_inode(inode, inode-i_mode, 0);if (ui-data_len ! 0) {err 14;goto out_invalid;}break;default:err 15;goto out_invalid;}kfree(ino);ubifs_set_inode_flags(inode);unlock_new_inode(inode);return inode;out_invalid:ubifs_err(c, inode %lu validation failed, error %d, inode-i_ino, err);ubifs_dump_node(c, ino);ubifs_dump_inode(c, inode);err -EINVAL; out_ino:kfree(ino); out:ubifs_err(c, failed to read inode %lu, error %d, inode-i_ino, err);iget_failed(inode);return ERR_PTR(err); } 将file的fop赋值为inode的fop 里面的f-f_op fops_get(inode-i_fop);对于/dev下的设备文件就是把上面init_special_inode里的inode-i_fop def_blk_fops;def_blk_fops的open为blkdev_open它又会调用块设备驱动实现的的open对于在文件系统中touch或者creat的文件就是文件系统实现的fops do_sys_opendo_filp_openpath_openatvfs_open do_dentry_openstatic int do_dentry_open(struct file *f,struct inode *inode,int (*open)(struct inode *, struct file )) {static const struct file_operations empty_fops {};int error;path_get(f-f_path);f-f_inode inode;f-f_mapping inode-i_mapping;/ Ensure that we skip any errors that predate opening of the file /f-f_wb_err filemap_sample_wb_err(f-f_mapping);if (unlikely(f-f_flags O_PATH)) {f-f_mode FMODE_PATH | FMODE_OPENED;f-f_op empty_fops;return 0;}/ Any file opened for execve()/uselib() has to be a regular file. /if (unlikely(f-f_flags FMODE_EXEC !S_ISREG(inode-i_mode))) {error -EACCES;goto cleanup_file;}if (f-f_mode FMODE_WRITE !special_file(inode-i_mode)) {error get_write_access(inode);if (unlikely(error))goto cleanup_file;error __mnt_want_write(f-f_path.mnt);if (unlikely(error)) {put_write_access(inode);goto cleanup_file;}f-f_mode | FMODE_WRITER;}/ POSIX.1-2008/SUSv4 Section XSI 2.9.7 /if (S_ISREG(inode-i_mode) || S_ISDIR(inode-i_mode))f-f_mode | FMODE_ATOMIC_POS;f-f_op fops_get(inode-i_fop);if (WARN_ON(!f-f_op)) {error -ENODEV;goto cleanup_all;}error security_file_open(f);if (error)goto cleanup_all;error break_lease(locks_inode(f), f-f_flags);if (error)goto cleanup_all;/ normally all 3 are set; -open() can clear them if needed /f-f_mode | FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE;if (!open)open f-f_op-open;if (open) {error open(inode, f);if (error)goto cleanup_all;}f-f_mode | FMODE_OPENED;if ((f-f_mode (FMODE_READ | FMODE_WRITE)) FMODE_READ)i_readcount_inc(inode);if ((f-f_mode FMODE_READ) likely(f-f_op-read || f-f_op-read_iter))f-f_mode | FMODE_CAN_READ;if ((f-f_mode FMODE_WRITE) likely(f-f_op-write || f-f_op-write_iter))f-f_mode | FMODE_CAN_WRITE;f-f_write_hint WRITE_LIFE_NOT_SET;f-f_flags ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);file_ra_state_init(f-f_ra, f-f_mapping-host-i_mapping);/ NB: were sure to have correct a_ops only after f_op-open /if (f-f_flags O_DIRECT) {if (!f-f_mapping-a_ops || !f-f_mapping-a_ops-direct_IO)return -EINVAL;}/** XXX: Huge page cache doesnt support writing yet. Drop all page cache for this file before processing writes.*/if ((f-f_mode FMODE_WRITE) filemap_nr_thps(inode-i_mapping))truncate_pagecache(inode, 0);return 0;cleanup_all:if (WARN_ON_ONCE(error 0))error -EINVAL;fops_put(f-f_op);if (f-f_mode FMODE_WRITER) {put_write_access(inode);__mnt_drop_write(f-f_path.mnt);} cleanup_file:path_put(f-f_path);f-f_path.mnt NULL;f-f_path.dentry NULL;f-f_inode NULL;return error; } 文件相关结构体 dentry 表示目录条目用于路径解析(将路径名转换为文件系统中的实际位置)和缓存(缓存最近访问的目录项),维护文件和目录之间的链接关系 d_name文件名或目录名。 d_inode指向该 dentry 对应的 inode。 d_parent指向父目录的 dentry。 d_subdirs指向子目录的链表头。 d_u用于缓存或其他用途的联合体。 d_sb指向文件系统的超级块super_block。 d_flags标志位用于控制 dentry 的行为。 d_count引用计数。 d_lockref锁和引用计数。 d_vfs_flagsVFS 标志。 d_alias用于哈希表的链表头 inode 表示文件或目录的元数据如文件类型、权限、时间戳;用于存储文件属性和操作函数。 i_inoinode 编号唯一标识一个 inode。 i_mode文件类型和权限。 i_uid文件所有者的用户 ID。 i_gid文件所有者的组 ID。 i_size文件大小。 i_atime上次访问时间。 i_mtime上次修改时间。 i_ctime上次状态改变时间。 i_links_count硬链接数。 i_blocks文件占用的块数。 i_blkbits块大小的对数值。 i_opinode 操作指针。 i_fop文件操作指针。 i_mapping地址空间映射。 i_private私有数据。 i_sb指向文件系统的超级块super_block。 file 表示打开文件用于文件操作和状态管理。 f_path指向文件的路径path包含 mnt 和 dentry。 f_inode指向文件的 inode。 f_mapping文件的地址空间映射。 f_mode文件的打开模式读、写、执行。 f_flags文件标志如 O_RDONLY、O_WRONLY、O_RDWR 等。 f_pos文件的当前读写位置。 f_op文件操作指针。 f_owner文件的所有者。 f_cred文件的凭证用户和组信息。 f_count引用计数。 f_version版本号用于检测文件状态变化。 f_wb_err写入错误。 f_sb_err超级块错误。 关系 一个 dentry 可以对应一个 inode多个 dentry 也可以对应同一个 inode硬链接 多个 file 结构体可以对应同一个 inode表示同一个文件被多次打开 file 结构体中的 f_op 指针指向 inode 中的 i_fop用于执行文件操作 file 结构体通过 f_path 引用 dentry确保文件路径的正确性 每个打开的文件描述符对应一个 file 结构体通过 file 结构体可以访问文件的 dentry 和 inode