Read and write files in the Linux kernel

Source: Internet
Author: User

http://blog.csdn.net/tommy_wxie/article/details/8194276

1. Overture

In the user state, read and write files can be completed by both the read and write system calls (the C library function is actually the encapsulation of the system call). However, there is no such system call in the kernel state, how can we read and write the file?

Read the Linux kernel source code, you can know that into the kernel execution is actually executed is sys_read and sys_write these two functions, but these two functions are not exported using Export_symbol, that is, other modules can not be used.

The specific implementation of system calls in FS/OPEN.C is as follows (Kernel version 2.6.34.1):

SYSCALL_DEFINE3 (open, const char __user *, filename, int, flags, int, mode)

{

LONG ret;

if (Force_o_largefile ())

Flags |= O_largefile;

ret = Do_sys_open (AT_FDCWD, filename, flags, mode);

/* Avoid regparm breakage on x86: */

Asmlinkage_protect (3, ret, filename, flags, mode);

return ret;

}

Trace the Do_sys_open () function, you will find that it mainly uses the Do_filp_open () function in Fs/namei.c, and in that file, the Filp_open function also calls the Do_filp_open function, and the interface and Sys_ The open function is very similar, the invocation parameter is the same as Sys_open, and is exported using Export_symbol, so we suspect that the function can open the file, the function is the same as open.

Using the same method, find a set of functions in the kernel operation file, as follows:

Function

Function prototypes

Open File

struct file *filp_open (const char *filename, int flags, int mode)

Read the file

ssize_t vfs_read (struct file *file, char __user *buf, size_t count, loff_t *pos)

Write a file

ssize_t vfs_write (struct file *file, const char __user *buf, size_t count, loff_t *pos)

Close File

int filp_close (struct file *filp, fl_owner_t ID)

2. Kernel Space and user space

In the Vfs_read and Vfs_write functions, their arguments buf to the memory address of the user space, and if we use a pointer to kernel space directly, we return-efalut. This is because the buffer used exceeds the address range of the user space. General system calls will require that you use a buffer that cannot be in the kernel area. This can be solved by set_fs (), Get_fs ().

In Include/asm/uaccess.h, there are the following definitions:

#define MAKE_MM_SEG (s) ((mm_segment_t) {(s)})

#define KERNEL_DS make_mm_seg (0xFFFFFFFF)

#define USER_DS make_mm_seg (Page_offset)

#define GET_DS () (Kernel_ds)

#define GET_FS () (Current->addr_limit)

#define SET_FS (x) (Current->addr_limit = (x))

If used, the following:

mm_segment_t fs = Get_fs ();

Set_fs (KERNEL_FS);

Vfs_write ();

Vfs_read ();

SET_FS (FS);

detailed Explanation: the system call would have been provided to the user space program Access, so, the parameters passed to it (such as the above buf), it will be considered by default from the user space, in the Read or write () function, in order to protect the kernel space, generally use GET_FS () The resulting value is compared with User_ds to prevent the user space program from "deliberately" destroying the kernel space, but now to use the system call in kernel space, the parameter address passed to read or write () is the address of the kernel space, above the User_ds (user_ds ~ KERNEL_DS), if you do not do any other processing, in the write () function, it will be considered that the address exceeds the User_ds range, so it will be considered as "deliberate destruction" of user space, so as to not allow further implementation; In order to solve this problem, set_fs (KERNEL_DS); Extend the space restrictions that it can access to kernel_ds so that system calls can be used successfully in the kernel!

With the support of VFS, the user-state process reads and writes to any type of file system can use read and write two system calls, but there is no such system call in the Linux kernel how do we manipulate files? We know that read and write after entering the kernel state, the actual execution is sys_read and sys_write, but look at the kernel source code, found that the functions of these operations files are not exported (using Export_symbol export), that is not available in the kernel module , how is that good?

By looking at the source code of Sys_open we found that it mainly uses the Do_filp_open () function, which is in Fs/namei.c, and in the change file, the Filp_open function also calls the Do_filp_open function, and the interface and Sys_ The open function is very similar, the invocation parameter is the same as Sys_open, and is exported using Export_symbol, so we suspect that the function can open the file, the function is the same as open. Using the same lookup method, we identified a set of functions that manipulate files in the kernel, as follows:

Function Function prototypes
Open File struct file *filp_open (const char *filename,int flags, int mode)
Read file ssize_t vfs_read (struct file *file,char __user *buf, size_t count, loff_t *pos)
Write a file ssize_t vfs_write (struct file *file,const char __user *buf,size_t count, loff_t *pos)
Close File int filp_close (struct file *filp, fl_owner_t ID)

We notice that in the Vfs_read and Vfs_write functions, their arguments buf to the memory address of the user space, and if we use a pointer to kernel space directly, we return-efalut. So we need to use
The Set_fs () and GET_FS () macros change the way the kernel handles memory address checks, so the read and write process for the files in kernel space is:

    1. Mm_segment_tfs = Get_fs ();
    2. Set_fs (KERNEL_FS);
    3. Vfs_write ();
    4. Vfs_read ();
    5. SET_FS (FS);

Here is an example of a file operation in the kernel:

    1. #include <linux/module.h>
    2. #include <linux/init.h>
    3. #include <linux/fs.h>
    4. #include <linux/uaccess.h>
    5. Static charbuf[] = "Hello";
    6. Static charbuf1[10];
    7. int __inithello_init (void)
    8. {
    9. struct file *fp;
    10. MM_SEGMENT_T FS;
    11. loff_t POS;
    12. PRINTK ("Hello enter/n");
    13. FP =filp_open ("/home/niutao/kernel_file", O_RDWR | o_creat,0644);
    14. if (Is_err (FP)) {
    15. PRINTK ("Create file error/n");
    16. return-1;
    17. }
    18. FS =get_fs ();
    19. Set_fs (Kernel_ds);
    20. pos = 0;
    21. Vfs_write (fp,buf, sizeof (BUF), &pos);
    22. pos = 0;
    23. Vfs_read (fp,buf1, sizeof (BUF), &pos);
    24. PRINTK ("read:%s/n", BUF1);
    25. Filp_close (FP,NULL);
    26. SET_FS (FS);
    27. return 0;
    28. }
    29. void __exithello_exit (void)
    30. {
    31. PRINTK ("Hello exit/n");
    32. }
    33. Module_init (Hello_init);
    34. Module_exit (Hello_exit);
    35. Module_license ("GPL");

Read and write files in the Linux kernel

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.