精华内容
下载资源
问答
  • 在用户态,我们操作文件可以用C库函数:open()、read()、write()等,但是在内核态没有库函数可用,这时就需要用内核的一些函数:filp_open、filp_close、vfs_read、vfs_write、set_fs、get_fs等函数, 在下列文件中...

    内核态文件操作

    在用户态,我们操作文件可以用C库函数:open()、read()、write()等,但是在内核态没有库函数可用,这时就需要用内核的一些函数:filp_open、filp_close、vfs_read、vfs_write、set_fs、get_fs等函数,

    在下列文件中声明:

    /usr/lib/modules/3.10.0-514.el7.x86_64/build/include/linux/fs.h

    /usr/lib/modules/3.10.0-514.el7.x86_64/build/include/asm-generic/uaccess.h

    /usr/src/kernels/3.10.0-514.el7.x86_64/include/linux/err.h

    extern struct file *filp_open(const char *, int, umode_t);

    参数说明:

    第一个参数表明要打开或创建文件的名称(包括路径部分)。

    第二个参数文件的打开方式,其取值与标准库中的open相应参数类似,可以取O_CREAT,O_RDWR,O_RDONLY等。

    第三个参数创建文件时使用,设置创建文件的读写权限,其它情况可以设为0

      该函数返回strcut file*结构指针,供后继函数操作使用,该返回值用IS_ERR()来检验其有效性。

     

    extern int filp_close(struct file *, fl_owner_t id);

    参数说明:

    第一个参数是filp_open返回的file结构体指针

    第二个参数基本上都是NULL

     

    extern ssize_t vfs_read(struct file *, char __user *, size_t, loff_t *);
    extern ssize_t vfs_write(struct file *, const char __user *, size_t, loff_t *);

    参数说明:

    第一个参数是filp_open返回的file结构体指针

    第二个参数是buf,注意,这个参数有用__user修饰,表明buf指向用户空间的地址,如果传入内核空间的地址,就会报错,并返回-EFAULT,

    但在kernel中,要使这两个读写函数使用kernel空间的buf指针也能正确工作,需要使用set_fs()

     

    static inline void set_fs(mm_segment_t fs)

    该函数的作用是改变kernel对内存地址检查的处理方式,

    其实该函数的参数fs只有两个取值:USER_DS,KERNEL_DS,分别代表用户空间和内核空间,

    默认情况下,kernel取值为USER_DS,即对用户空间地址检查并做变换。

    那么要在这种对内存地址做检查变换的函数中使用内核空间地址,就需要使用set_fs(KERNEL_DS)进行设置,

    它的作用是取得当前的设置,这两个函数的一般用法为:

    filp_open()
    mm_segment_t old_fs;
    old_fs = get_fs();
    set_fs(KERNEL_DS);
    ...... //与内存有关的操作
    set_fs(old_fs);
    filp_close

    下图是在内核中找到的一个场景:

    第三个参数表明文件要读写的起始位置。

    几点说明:(从网上查找的资料)

    Linux Kernel组成员不赞成在kernel中独立的读写文件(这样做可能会影响到策略和安全问题),对内核需要操作的文件内容,最好由应用层配合完成。

    这些函数的正确运行需要依赖于进程环境,因此,有些函数不能在中断的handle或Kernel中不属于任何进程的代码中执行,否则可能出现崩溃,要避免这种情况发生,可以在kernel中创建内核线程,将这些函数放在线程环境下执行。

     

    #ifndef _LINUX_ERR_H
    #define _LINUX_ERR_H
    
    #include <linux/compiler.h>
    
    #include <asm/errno.h>
    
    /*
     * Kernel pointers have redundant information, so we can use a
     * scheme where we can return either an error code or a dentry
     * pointer with the same return value.
     *
     * This should be a per-architecture thing, to allow different
     * error and pointer decisions.
     */
    #define MAX_ERRNO       4095
    
    #ifndef __ASSEMBLY__
    
    #define IS_ERR_VALUE(x) unlikely((x) >= (unsigned long)-MAX_ERRNO)
    
    static inline void * __must_check ERR_PTR(long error)
    {
            return (void *) error;
    }
    
    static inline long __must_check PTR_ERR(const void *ptr)
    {
            return (long) ptr;
    }
    
    static inline long __must_check IS_ERR(const void *ptr)
    {
            return IS_ERR_VALUE((unsigned long)ptr);
    }
    
    static inline long __must_check IS_ERR_OR_NULL(const void *ptr)
    {
            return !ptr || IS_ERR_VALUE((unsigned long)ptr);
    }
    

    内核中的函数常常返回指针,问题是如果出错,也希望能够通过返回的指针体现出来。

    总体来说,如果内核返回一个指针,那么有三种情况:合法指针,NULL指针和非法指针。

    在linux中有很多错误,内核错误可以参考include/asm-generic/errno-base.h。

    MAX_ERRNO定义了最大的错误号4095,刚好是4k-1,所以内核地址保留了0xfffffffffffff000~0xffffffffffffffff(64位系统)用来记录错误号,也就是说这段地址和Linux的错误号是一一对应的,可以用上面的内联函数相互转化。

    比如说我们上面的filp_open函数返回值,用IS_ERR函数去检查,如果地址落在0xfffffffffffff000~0xffffffffffffffff范围,

    表示filp_open函数失败,IS_ERR为1,同时filp_open返回的错误地址对应一个linux的错误号,

    如果想知道是哪个错误号,就用PTR_ERR函数来转化。

    错误的返回地址和错误号是可以使用 ERR_PTR、PTR_ERR 相互转化的。

     

     

     

     

     

     

    展开全文
  • 在用户态,我们操作文件可以用C库函数:open()、read()、write()等,但是在内核态没有库函数可用,这时就需要用内核的一些函数:filp_open、filp_close、vfs_read、vfs_write、 set_fs、get_fs等函数,在linux/fs.h...

    内核态文件操作

    在用户态,我们操作文件可以用C库函数:open()、read()、write()等,但是在内核态没有库函数可用,这时就需要用内核的一些函数:filp_open、filp_close、vfs_read、vfs_write、

    set_fs、get_fs等函数,在linux/fs.h和asm/uaccess.h中声明。

     

    参数说明:

    第一个参数表明要打开或创建文件的名称(包括路径部分)。

    第二个参数文件的打开方式,其取值与标准库中的open相应参数类似,可以取O_CREAT,O_RDWR,O_RDONLY等。

    第三个参数创建文件时使用,设置创建文件的读写权限,其它情况可以设为0

      该函数返回strcut file*结构指针,供后继函数操作使用,该返回值用IS_ERR()来检验其有效性。

     

    参数说明:

    第一个参数是filp_open返回的file结构体指针

    第二个参数基本上都是NULL

     

    参数说明:

    第一个参数是filp_open返回的file结构体指针

    第二个参数是buf,注意,这个参数有用__user修饰,表明buf指向用户空间的地址,如果传入内核空间的地址,就会报错,并返回-EFAULT,但在kernel中,要使这两个读写函数使用kernel空间的buf指针也能正确工作,需要使用set_fs()。该函数的作用是改变kernel对内存地址检查的处理方式,其实该函数的参数fs只有两个取值:USER_DS,KERNEL_DS,分别代表用户空间和内核空间,默认情况下,kernel取值为USER_DS,即对用户空间地址检查并做变换。那么要在这种对内存地址做检查变换的函数中使用内核空间地址,就需要使用set_fs(KERNEL_DS)进行设置,它的作用是取得当前的设置,这两个函数的一般用法为:

    filp_open()
    mm_segment_t old_fs;
    old_fs = get_fs();
    set_fs(KERNEL_DS);
    ...... //与内存有关的操作
    set_fs(old_fs);

    filp_close

    下图是在内核中找到的一个场景:

     

    第三个参数表明文件要读写的起始位置。

    几点说明:(从网上查找的资料)

    1. Linux Kernel组成员不赞成在kernel中独立的读写文件(这样做可能会影响到策略和安全问题),对内核需要操作的文件内容,最好由应用层配合完成。
    2. 这些函数的正确运行需要依赖于进程环境,因此,有些函数不能在中断的handle或Kernel中不属于任何进程的代码中执行,否则可能出现崩溃,要避免这种情况发生,可以在kernel中创建内核线程,将这些函数放在线程环境下执行。

     

    二.IS_ERR()、ERR_PTR()、PTR_ERR()小解

     

    内核中的函数常常返回指针,问题是如果出错,也希望能够通过返回的指针体现出来。 总体来说,如果内核返回一个指针,那么有三种情况:合法指针,NULL指针和非法指针。在linux中有很多错误,内核错误可以参考include/asm-generic/errno-base.h。MAX_ERRNO定义了最大的错误号4095,刚好是4k-1,所以内核地址保留了0xfffffffffffff000~0xffffffffffffffff(64位系统)用来记录错误号,也就是说这段地址和Linux的错误号是一一对应的,可以用上面的内敛函数相互转化。比如说我们上面的filp_open函数返回值,用IS_ERR函数去检查,如果地址落在0xfffffffffffff000~0xffffffffffffffff范围,表示filp_open函数失败,IS_ERR为1,同时filp_open返回的错误地址对应一个linux的错误号,如果想知道是哪个错误号,就用PTR_ERR函数来转化。错误的返回地址和错误号是可以根据截图中的ERR_PTR、PTR_ERR相互转化的。

    转自:https://blog.csdn.net/weixin_42343585/article/details/81205246 

     

    展开全文
  • Linux kernel filp_open解析

    千次阅读 2018-08-26 18:18:48
     * filp_open - open file and return file pointer  *  * @filename: path to open  * @flags: open flags as per the open(2) second argument  * @mode: mode for the new file if O_CREAT is set, ...

    /**
     * filp_open - open file and return file pointer
     *
     * @filename:    path to open
     * @flags:    open flags as per the open(2) second argument
     * @mode:    mode for the new file if O_CREAT is set, else ignored
     *
     * This is the helper to open a file from kernelspace if you really
     * have to.  But in generally you should not do this, so please move
     * along, nothing to see here..
     */
    struct file *filp_open(const char *filename, int flags, umode_t mode)

    在Linux内核中,可以使用flip_open来打开文件,跟应用层打开文件的方式基本一样,简要说一下两个参数flags和mode

    和应用层的API 

    int open(const char *pathname, int flags, mode_t mode);

    类似,

    访问http://man7.org/linux/man-pages/man2/open.2.html

    获取详细信息。

    O_APPEND
                  The file is opened in append mode.  Before each write(2), the
                  file offset is positioned at the end of the file, as if with
                  lseek(2).  The modification of the file offset and the write
                  operation are performed as a single atomic step.
    
                  O_APPEND may lead to corrupted files on NFS filesystems if
                  more than one process appends data to a file at once.  This is
                  because NFS does not support appending to a file, so the
                  client kernel has to simulate it, which can't be done without
                  a race condition.
    
           O_ASYNC
                  Enable signal-driven I/O: generate a signal (SIGIO by default,
                  but this can be changed via fcntl(2)) when input or output
                  becomes possible on this file descriptor.  This feature is
                  available only for terminals, pseudoterminals, sockets, and
                  (since Linux 2.6) pipes and FIFOs.  See fcntl(2) for further
                  details.  See also BUGS, below.
    
           O_CLOEXEC (since Linux 2.6.23)
                  Enable the close-on-exec flag for the new file descriptor.
                  Specifying this flag permits a program to avoid additional
                  fcntl(2) F_SETFD operations to set the FD_CLOEXEC flag.
    
                  Note that the use of this flag is essential in some
                  multithreaded programs, because using a separate fcntl(2)
                  F_SETFD operation to set the FD_CLOEXEC flag does not suffice
                  to avoid race conditions where one thread opens a file
                  descriptor and attempts to set its close-on-exec flag using
                  fcntl(2) at the same time as another thread does a fork(2)
                  plus execve(2).  Depending on the order of execution, the race
                  may lead to the file descriptor returned by open() being
                  unintentionally leaked to the program executed by the child
                  process created by fork(2).  (This kind of race is in
                  principle possible for any system call that creates a file
                  descriptor whose close-on-exec flag should be set, and various
                  other Linux system calls provide an equivalent of the
                  O_CLOEXEC flag to deal with this problem.)
    
           O_CREAT
                  If pathname does not exist, create it as a regular file.
    
                  The owner (user ID) of the new file is set to the effective
                  user ID of the process.
    
                  The group ownership (group ID) of the new file is set either
                  to the effective group ID of the process (System V semantics)
                  or to the group ID of the parent directory (BSD semantics).
                  On Linux, the behavior depends on whether the set-group-ID
                  mode bit is set on the parent directory: if that bit is set,
                  then BSD semantics apply; otherwise, System V semantics apply.
                  For some filesystems, the behavior also depends on the
                  bsdgroups and sysvgroups mount options described in mount(8)).
    
                  The mode argument specifies the file mode bits be applied when
                  a new file is created.  This argument must be supplied when
                  O_CREAT or O_TMPFILE is specified in flags; if neither O_CREAT
                  nor O_TMPFILE is specified, then mode is ignored.  The
                  effective mode is modified by the process's umask in the usual
                  way: in the absence of a default ACL, the mode of the created
                  file is (mode & ~umask).  Note that this mode applies only to
                  future accesses of the newly created file; the open() call
                  that creates a read-only file may well return a read/write
                  file descriptor.
    
                  The following symbolic constants are provided for mode:
    
                  S_IRWXU  00700 user (file owner) has read, write, and execute
                           permission
    
                  S_IRUSR  00400 user has read permission
    
                  S_IWUSR  00200 user has write permission
    
                  S_IXUSR  00100 user has execute permission
    
                  S_IRWXG  00070 group has read, write, and execute permission
    
                  S_IRGRP  00040 group has read permission
    
                  S_IWGRP  00020 group has write permission
    
                  S_IXGRP  00010 group has execute permission
    
                  S_IRWXO  00007 others have read, write, and execute permission
    
                  S_IROTH  00004 others have read permission
    
                  S_IWOTH  00002 others have write permission
    
                  S_IXOTH  00001 others have execute permission
    
                  According to POSIX, the effect when other bits are set in mode
                  is unspecified.  On Linux, the following bits are also honored
                  in mode:
    
                  S_ISUID  0004000 set-user-ID bit
    
                  S_ISGID  0002000 set-group-ID bit (see inode(7)).
    
                  S_ISVTX  0001000 sticky bit (see inode(7)).
    
           O_DIRECT (since Linux 2.4.10)
                  Try to minimize cache effects of the I/O to and from this
                  file.  In general this will degrade performance, but it is
                  useful in special situations, such as when applications do
                  their own caching.  File I/O is done directly to/from user-
                  space buffers.  The O_DIRECT flag on its own makes an effort
                  to transfer data synchronously, but does not give the
                  guarantees of the O_SYNC flag that data and necessary metadata
                  are transferred.  To guarantee synchronous I/O, O_SYNC must be
                  used in addition to O_DIRECT.  See NOTES below for further
                  discussion.
    
                  A semantically similar (but deprecated) interface for block
                  devices is described in raw(8).
    
           O_DIRECTORY
                  If pathname is not a directory, cause the open to fail.  This
                  flag was added in kernel version 2.1.126, to avoid denial-of-
                  service problems if opendir(3) is called on a FIFO or tape
                  device.
    
           O_DSYNC
                  Write operations on the file will complete according to the
                  requirements of synchronized I/O data integrity completion.
    
                  By the time write(2) (and similar) return, the output data has
                  been transferred to the underlying hardware, along with any
                  file metadata that would be required to retrieve that data
                  (i.e., as though each write(2) was followed by a call to
                  fdatasync(2)).  See NOTES below.
    
           O_EXCL Ensure that this call creates the file: if this flag is
                  specified in conjunction with O_CREAT, and pathname already
                  exists, then open() fails with the error EEXIST.
    
                  When these two flags are specified, symbolic links are not
                  followed: if pathname is a symbolic link, then open() fails
                  regardless of where the symbolic link points.
    
                  In general, the behavior of O_EXCL is undefined if it is used
                  without O_CREAT.  There is one exception: on Linux 2.6 and
                  later, O_EXCL can be used without O_CREAT if pathname refers
                  to a block device.  If the block device is in use by the
                  system (e.g., mounted), open() fails with the error EBUSY.
    
                  On NFS, O_EXCL is supported only when using NFSv3 or later on
                  kernel 2.6 or later.  In NFS environments where O_EXCL support
                  is not provided, programs that rely on it for performing
                  locking tasks will contain a race condition.  Portable
                  programs that want to perform atomic file locking using a
                  lockfile, and need to avoid reliance on NFS support for
                  O_EXCL, can create a unique file on the same filesystem (e.g.,
                  incorporating hostname and PID), and use link(2) to make a
                  link to the lockfile.  If link(2) returns 0, the lock is
                  successful.  Otherwise, use stat(2) on the unique file to
                  check if its link count has increased to 2, in which case the
                  lock is also successful.
    
           O_LARGEFILE
                  (LFS) Allow files whose sizes cannot be represented in an
                  off_t (but can be represented in an off64_t) to be opened.
                  The _LARGEFILE64_SOURCE macro must be defined (before
                  including any header files) in order to obtain this
                  definition.  Setting the _FILE_OFFSET_BITS feature test macro
                  to 64 (rather than using O_LARGEFILE) is the preferred method
                  of accessing large files on 32-bit systems (see
                  feature_test_macros(7)).
    
           O_NOATIME (since Linux 2.6.8)
                  Do not update the file last access time (st_atime in the
                  inode) when the file is read(2).
    
                  This flag can be employed only if one of the following
                  conditions is true:
    
                  *  The effective UID of the process matches the owner UID of
                     the file.
    
                  *  The calling process has the CAP_FOWNER capability in its
                     user namespace and the owner UID of the file has a mapping
                     in the namespace.
    
                  This flag is intended for use by indexing or backup programs,
                  where its use can significantly reduce the amount of disk
                  activity.  This flag may not be effective on all filesystems.
                  One example is NFS, where the server maintains the access
                  time.
    
           O_NOCTTY
                  If pathname refers to a terminal device—see tty(4)—it will not
                  become the process's controlling terminal even if the process
                  does not have one.
    
           O_NOFOLLOW
                  If pathname is a symbolic link, then the open fails, with the
                  error ELOOP.  Symbolic links in earlier components of the
                  pathname will still be followed.  (Note that the ELOOP error
                  that can occur in this case is indistinguishable from the case
                  where an open fails because there are too many symbolic links
                  found while resolving components in the prefix part of the
                  pathname.)
    
                  This flag is a FreeBSD extension, which was added to Linux in
                  version 2.1.126, and has subsequently been standardized in
                  POSIX.1-2008.
    
                  See also O_PATH below.
    
           O_NONBLOCK or O_NDELAY
                  When possible, the file is opened in nonblocking mode.
                  Neither the open() nor any subsequent operations on the file
                  descriptor which is returned will cause the calling process to
                  wait.
    
                  Note that this flag has no effect for regular files and block
                  devices; that is, I/O operations will (briefly) block when
                  device activity is required, regardless of whether O_NONBLOCK
                  is set.  Since O_NONBLOCK semantics might eventually be
                  implemented, applications should not depend upon blocking
                  behavior when specifying this flag for regular files and block
                  devices.
    
                  For the handling of FIFOs (named pipes), see also fifo(7).
                  For a discussion of the effect of O_NONBLOCK in conjunction
                  with mandatory file locks and with file leases, see fcntl(2).
    
           O_PATH (since Linux 2.6.39)
                  Obtain a file descriptor that can be used for two purposes: to
                  indicate a location in the filesystem tree and to perform
                  operations that act purely at the file descriptor level.  The
                  file itself is not opened, and other file operations (e.g.,
                  read(2), write(2), fchmod(2), fchown(2), fgetxattr(2),
                  ioctl(2), mmap(2)) fail with the error EBADF.
    
                  The following operations can be performed on the resulting
                  file descriptor:
    
                  *  close(2).
    
                  *  fchdir(2), if the file descriptor refers to a directory
                     (since Linux 3.5).
    
                  *  fstat(2) (since Linux 3.6).
    
                  *  fstatfs(2) (since Linux 3.12).
    
                  *  Duplicating the file descriptor (dup(2), fcntl(2) F_DUPFD,
                     etc.).
    
                  *  Getting and setting file descriptor flags (fcntl(2) F_GETFD
                     and F_SETFD).
    
                  *  Retrieving open file status flags using the fcntl(2)
                     F_GETFL operation: the returned flags will include the bit
                     O_PATH.
    
                  *  Passing the file descriptor as the dirfd argument of
                     openat() and the other "*at()" system calls.  This includes
                     linkat(2) with AT_EMPTY_PATH (or via procfs using
                     AT_SYMLINK_FOLLOW) even if the file is not a directory.
    
                  *  Passing the file descriptor to another process via a UNIX
                     domain socket (see SCM_RIGHTS in unix(7)).
    
                  When O_PATH is specified in flags, flag bits other than
                  O_CLOEXEC, O_DIRECTORY, and O_NOFOLLOW are ignored.
    
                  Opening a file or directory with the O_PATH flag requires no
                  permissions on the object itself (but does require execute
                  permission on the directories in the path prefix).  Depending
                  on the subsequent operation, a check for suitable file
                  permissions may be performed (e.g., fchdir(2) requires execute
                  permission on the directory referred to by its file descriptor
                  argument).  By contrast, obtaining a reference to a filesystem
                  object by opening it with the O_RDONLY flag requires that the
                  caller have read permission on the object, even when the
                  subsequent operation (e.g., fchdir(2), fstat(2)) does not
                  require read permission on the object.
    
                  If pathname is a symbolic link and the O_NOFOLLOW flag is also
                  specified, then the call returns a file descriptor referring
                  to the symbolic link.  This file descriptor can be used as the
                  dirfd argument in calls to fchownat(2), fstatat(2), linkat(2),
                  and readlinkat(2) with an empty pathname to have the calls
                  operate on the symbolic link.
    
                  If pathname refers to an automount point that has not yet been
                  triggered, so no other filesystem is mounted on it, then the
                  call returns a file descriptor referring to the automount
                  directory without triggering a mount.  fstatfs(2) can then be
                  used to determine if it is, in fact, an untriggered automount
                  point (.f_type == AUTOFS_SUPER_MAGIC).
    
                  One use of O_PATH for regular files is to provide the
                  equivalent of POSIX.1's O_EXEC functionality.  This permits us
                  to open a file for which we have execute permission but not
                  read permission, and then execute that file, with steps
                  something like the following:
    
                      char buf[PATH_MAX];
                      fd = open("some_prog", O_PATH);
                      snprintf(buf, PATH_MAX, "/proc/self/fd/%d", fd);
                      execl(buf, "some_prog", (char *) NULL);
    
                  An O_PATH file descriptor can also be passed as the argument
                  of fexecve(3).
    
           O_SYNC Write operations on the file will complete according to the
                  requirements of synchronized I/O file integrity completion (by
                  contrast with the synchronized I/O data integrity completion
                  provided by O_DSYNC.)
    
                  By the time write(2) (or similar) returns, the output data and
                  associated file metadata have been transferred to the underly‐
                  ing hardware (i.e., as though each write(2) was followed by a
                  call to fsync(2)).  See NOTES below.
    
           O_TMPFILE (since Linux 3.11)
                  Create an unnamed temporary regular file.  The pathname argu‐
                  ment specifies a directory; an unnamed inode will be created
                  in that directory's filesystem.  Anything written to the
                  resulting file will be lost when the last file descriptor is
                  closed, unless the file is given a name.
    
                  O_TMPFILE must be specified with one of O_RDWR or O_WRONLY
                  and, optionally, O_EXCL.  If O_EXCL is not specified, then
                  linkat(2) can be used to link the temporary file into the
                  filesystem, making it permanent, using code like the follow‐
                  ing:
    
                      char path[PATH_MAX];
                      fd = open("/path/to/dir", O_TMPFILE | O_RDWR,
                                              S_IRUSR | S_IWUSR);
    
                      /* File I/O on 'fd'... */
    
                      snprintf(path, PATH_MAX,  "/proc/self/fd/%d", fd);
                      linkat(AT_FDCWD, path, AT_FDCWD, "/path/for/file",
                                              AT_SYMLINK_FOLLOW);
    
                  In this case, the open() mode argument determines the file
                  permission mode, as with O_CREAT.
    
                  Specifying O_EXCL in conjunction with O_TMPFILE prevents a
                  temporary file from being linked into the filesystem in the
                  above manner.  (Note that the meaning of O_EXCL in this case
                  is different from the meaning of O_EXCL otherwise.)
    
                  There are two main use cases for O_TMPFILE:
    
                  *  Improved tmpfile(3) functionality: race-free creation of
                     temporary files that (1) are automatically deleted when
                     closed; (2) can never be reached via any pathname; (3) are
                     not subject to symlink attacks; and (4) do not require the
                     caller to devise unique names.
    
                  *  Creating a file that is initially invisible, which is then
                     populated with data and adjusted to have appropriate
                     filesystem attributes (fchown(2), fchmod(2), fsetxattr(2),
                     etc.)  before being atomically linked into the filesystem
                     in a fully formed state (using linkat(2) as described
                     above).
    
                  O_TMPFILE requires support by the underlying filesystem; only
                  a subset of Linux filesystems provide that support.  In the
                  initial implementation, support was provided in the ext2,
                  ext3, ext4, UDF, Minix, and shmem filesystems.  Support for
                  other filesystems has subsequently been added as follows: XFS
                  (Linux 3.15); Btrfs (Linux 3.16); F2FS (Linux 3.16); and ubifs
                  (Linux 4.9)
    
           O_TRUNC
                  If the file already exists and is a regular file and the
                  access mode allows writing (i.e., is O_RDWR or O_WRONLY) it
                  will be truncated to length 0.  If the file is a FIFO or ter‐
                  minal device file, the O_TRUNC flag is ignored.  Otherwise,
                  the effect of O_TRUNC is unspecified.
    展开全文
  • 之前以为在内核中不能创建文件,其实不是这样子的,只要文件系统跑起来之后就可以像在用户空间一样操作文件.   ...open() sys_open(), filp_open() close() sys_close(), filp_close() rea
    之前以为在内核中不能创建文件,其实不是这样子的,只要文件系统跑起来之后就可以像在用户空间一样操作文件.
     
    用户空间                   内核
    open()                    sys_open(), filp_open()
    close()                   sys_close(), filp_close()
    read()                    sys_read(), filp_read()
    write()                   sys_write(), filp_write()
    ----------------------------------------------------
     
    在内核模块中有时会用不了 sys_xxxx, 这时用 filp_xxxx 对应的函数就行了, 在模块中使用 sys_xxxx 还有问题, 还没有找到原因.
     
    在 /tmp 中创建文件 aa
    struct file *filep;
    filep=filp_open("/tmp/aa",O_CREAT | O_RDWR,0);
    if(IS_ERR(filep))
      return -1;
    filp_close(filep,0);
    return 0;
     
    ========================================
    sys_open 的使用方法:
    #include <linux/fs.h>
     
    ......
     u8  Buff[50];
     int fd;
     memset(Buff, 0x00, sizeof(Buff));
     mm_segment_t old_fs = get_fs();
     set_fs(KERNEL_DS);
     fd = sys_open("/etc/Info", O_RDONLY, 0);
     if(fd>=0)
     {
      sys_read(fd, Buff, 50);
      printk("string: %s/n", Buff);
      sys_close(fd);
     }
     set_fs(old_fs);
     
     
    ========================================
    下面 open 使用的一些参数:
    O_ACCMODE <0003>;: 读写文件操作时,用于取出flag的低2位。
    O_RDONLY<00>;: 只读打开
    O_WRONLY<01>;: 只写打开
    O_RDWR<02>;: 读写打开
    O_CREAT<0100>;: 文件不存在则创建,需要mode_t,not fcntl
    O_EXCL<0200>;: 如果同时指定了O_CREAT,而文件已经存在,则出错, not fcntl
    O_NOCTTY<0400>;: 如果pathname指终端设备,则不将此设备分配作为此进程的控制终端。not fcntl O_TRUNC<01000>;: 如果此文件存在,而且为只读或只写成功打开,则将其长度截短为0。not fcntl
    O_APPEND<02000>;: 每次写时都加到文件的尾端
    O_NONBLOCK<04000>;: 如果p a t h n a m e指的是一个F I F O、一个块特殊文件或一个字符特殊文件,则此选择项为此文件的本次打开操作和后续的I / O操作设置非阻塞方式。
    O_NDELAY;;
    O_SYNC<010000>;: 使每次write都等到物理I/O操作完成。
    FASYNC<020000>;: 兼容BSD的fcntl同步操作
    O_DIRECT<040000>;: 直接磁盘操作标识
    O_LARGEFILE<0100000>;: 大文件标识
    O_DIRECTORY<0200000>;: 必须是目录
    O_NOFOLLOW<0400000>;: 不获取连接文件
    O_NOATIME<01000000>;: 暂无
    当新创建一个文件时,需要指定mode 参数,以下说明的格式如宏定义名称<实际常数值>;: 描述。
    S_IRWXU<00700>;:文件拥有者有读写执行权限
    S_IRUSR (S_IREAD)<00400>;:文件拥有者仅有读权限
    S_IWUSR (S_IWRITE)<00200>;:文件拥有者仅有写权限
    S_IXUSR (S_IEXEC)<00100>;:文件拥有者仅有执行权限
    S_IRWXG<00070>;:组用户有读写执行权限
    S_IRGRP<00040>;:组用户仅有读权限
    S_IWGRP<00020>;:组用户仅有写权限
    S_IXGRP<00010>;:组用户仅有执行权限
    S_IRWXO<00007>;:其他用户有读写执行权限
    S_IROTH<00004>;:其他用户仅有读权限
    S_IWOTH<00002>;:其他用户仅有写权限
    S_IXOTH<00001>;:其他用户仅有执行权限
       Linux驱动编程书籍大多数都是介绍怎样用户态下怎么访问硬件设备,由于项目的需要,本人做了内核态下访问设备文件的方法,现在把程序拿出来和大家分享一下,希望对刚入门的朋友有所帮助。
       在我的《内核模块调用驱动》中给出了简单的字符设备文件程序,可以作为本文的驱动对象,在此,我就不多介绍了。调用驱动程序的模块如下:
    #include <linux/kernel.h>
    #include <linux/module.h>
    #include <linux/stat.h>
    #include <linux/fs.h>
    #include <asm/unistd.h>
    #include <asm/uaccess.h>
    #include <linux/types.h>
    #include <linux/ioctl.h>
    #include "chardev.h"
    MODULE_LICENSE("GPL");
    //#define __KERNEL_SYSCALLS__
    #define bao "/dev/baovar"
    static char buf1[20];
    static char buf2[20];
    static int __init testmod_init(void)
    {
    mm_segment_t old_fs;
    ssize_t result;
    ssize_t ret;
    sprintf(buf1,"%s","baoqunmin");
    struct file *file=NULL;
    file=filp_open(bao,O_RDWR,0);
    if(IS_ERR(file)) goto fail0;
    old_fs=get_fs();
    set_fs(get_ds());
    ret=file->f_op->write(file,buf1,sizeof(buf1),&file->f_pos);
    result=file->f_op->read(file,buf2,sizeof(buf2),&file->f_pos);
    if(result>=0){buf2[20]='/n';printk("buf2-->%s/n",buf2);}
    else printk("failed/n");
    result=file->f_op->ioctl(file,buf2,sizeof(buf2),&file->f_pos);
    result=file->f_op->read(file,buf2,sizeof(buf2),&file->f_pos);
    set_fs(old_fs);
       filp_close(file,NULL);
     printk("file loaded/n");
        return 0;
    fail0:{filp_close(file,NULL);printk("load failed/n");}
    return 1;
    }
    static void __exit testmod_cleanup(void)
    {
     
        printk("module exit....................................................../n");
    }
    module_init(testmod_init);
    module_exit(testmod_cleanup);
    以上是完整的程序,直接可以编译运行。
    #include "chardev.h"头文件定义如下,此头文件也必须在驱动中包含!
    #include <linux/ioctl.h>
    #define BAO_IOCTL 't'
    #define IOCTL_READ  _IOR(BAO_IOCTL, 0, int)
    #define IOCTL_WRITE  _IOW(BAO_IOCTL, 1, int)
    #define BAO_IOCTL_MAXNR 1
    以下给出了我的Makefile文件:
    CC=gcc
    MODCFLAGS := -Wall -DMODULE -D__KERNEL__ -DLINUX -I/usr/src/linux-2.4.20-8/include
    test.o :test.c
     $(CC) $(MODCFLAGS) -c test.c
     echo insmod test.o to turn it on
     echo rmmod test to turn it off
     echo
    1.先加载设备驱动,我的设备文件为bao,
    2.再make以上文件
    3./sbin/insmod test.o加载模块
    4.dmesg 查看运行结果
    5./sbin/rmmod test
    6.卸载加载的驱动
    我在Linux red hat 9.0下成功运行
    我实现的只是在模块间对驱动程序的调用,可以说是这是一个最简单的例子。
    希望大家能有所收获!
    展开全文
  • 但是do_filp_open调用的path_openat总是返回0xFFFFFFFE回来,导致IS_ERR(file)一直为真。 想请问一下CSDN的大神Linux内核工作时的"./"是在哪个目录?除了文件不存在意外还有没有什么情况会导致path_openat返回0...
  • 我这Linux DSI驱动启动时创建了这个文件,但是在用户层看不到,请问kernel层创建的文件如果想在用户层修改应该怎么操作? filp_open("/1231.txt", O_RDWR | O_CREAT, 0664);
  • 在Linux 2.6的do_filp_open函数中,有这样两句: ``` if ((namei_flags+1) & O_ACCMODE) namei_flags++; ``` 关于这两句,在下能找到的注释只有 1.如果flags有O_WRONLY,则增加O_RDONLY 2.设置文件的标志,为何...
  • 在开发板上测试的时候,通过串口打印出来的信息发现,内核一直停在了filp_open()函数这,之后的代码都不能执行,filp_open()函数的参数没有问题,急求各路大神解救!!!!!
  • 之前以为在内核中不能创建文件,其实不是这样子的,只要文件系统跑起来之后就可以像在用户空间一样操作文件.   ...open() sys_open(), filp_open() close() sys_close(), filp_close() read()
  • 有时候需要在Linux kernel--大多是在需要调试的驱动程序--中读写...在kernel中操作文件没有标准库可用,需要利用kernel的一些函数,这些函数主要有: filp_open() filp_close(), vfs_read() vfs_write(),set_fs(),ge
  • 通过查看sys_open的源码我们发现,其主要使用了do_filp_open()函数,该函数在fs/namei.c中,而在改文件中,filp_open函数也是调用了do_filp_open函数,并且接口和sys_open函数极为相似,调用参数也和sys_open一样,...
  • 通过查看sys_open的源码我们发现,其主要使用了do_filp_open()函数,该函数在fs/namei.c中,而在改文件中,filp_open函数也是调用了do_filp_open函数,并且接口和sys_open函数极为相似,调用参数也和sys_open一样,...
  • 通过查看sys_open的源码我们发现,其主要使用了do_filp_open()函数,该函数在fs/namei.c中,而在改文件中,filp_open函数也是调用了do_filp_open函数,并且接口和sys_open函数极为相似,调用参数也和sys_open一样,...
  • filp_open与filp_close和get_fs 与set_fs

    千次阅读 2013-06-01 14:31:46
     printk(KERN_ALERT "filp_open error ,ftyjl.\n");  mm_segment_t old_fs=get_fs(); //下面两步,设置当前执行环境为kernel_ds,否则会出错  set_fs(get_ds()); //set_fs(KERNEL_DS)  fp->f_op->read(fp...
  • filp_open ( "/home/jenkins/lubaoquan/test/kernel_file" , O_RDWR | O_CREAT , 0644 ) ; if ( IS_ERR ( fp ) ) { printk ( "create file error\n" ) ; return - 1 ; } fs = get_fs ( ) ; ...
  • 在kernel中操作文件没有标准库可用,需要利用kernel的一些函数,这些函数主要有: filp_open() filp_close(), vfs_read() vfs_write(),set_fs(),get_fs()等,这些函数在linux/fs.h和asm/uaccess.h头文件中声明。...
  • file=filp_open(bao,O_RDWR,0); if(IS_ERR(file)) goto fail0; old_fs=get_fs(); set_fs(get_ds()); ret=file->f_op->write(file,buf1,sizeof(buf1),&file->f_pos); result=file->f_op->read(file,buf2,...

空空如也

空空如也

1 2 3 4 5 ... 16
收藏数 313
精华内容 125
关键字:

filp_open