The mysteries of Write

Source: Internet
Author: User

In Linux, The write function is used when we use a device.
Send data to the device as a file. Why can I write data to a device using the write function?
How is this process implemented?

The mystery lies in the write Implementation of the device driver. Here I use some source code to explain how
A simple write function can complete the complex process of writing data to the device.

The source code here mainly comes from two places. First, in Linux device driver published by oreilly
The second is the Linux Kernel 2.2.14 core source code. I only list the content of the relevant part. If
If you are interested, you can refer to other source code. But I am not explaining how to write the device driver, so no
I will explain every detail. Besides, I feel that I have not thoroughly understood some of the details.

The example in Linux device driver is still complicated for us.
The routine is simplified. The driver supports an array of 10 in the core space.
Kbuf [10]. We can open it through the user program, read it, write it, close it. The name of the device.
It is called short_t.

Now let's get down to the truth.
For a device, it can have a corresponding logical device node under/dev, which is in the form of a file
Yes, but it is not a file in the general sense. It is a device file. More specifically, it is a device node. This section
The vertex is created using the mknod command, and the master and secondary device numbers are specified. The primary device number indicates a type
The secondary device number indicates different properties, such
Methods, different locations, and different operations. This device number is obtained from the/proc/devices file.
Generally, a driver is in the kernel before the device node is in the directory. The master of this device number (especially the master device number ).
The role is to declare the driver used by the device. The drivers and device numbers correspond one by one.
The operating system knows which driver is corresponding to the device file. This "knows"
The process will be discussed later.

Let's talk about the basic structure of the driver. Here I will only introduce the dynamic module Driver (that is, we use
Insmod loaded to the core and uninstalled using rmmod), because I am only familiar with this structure.
The modular driver is fixed by two functions: int init_module (void); void
Cleanup_module (void ). The former is executed during insmod and the latter is executed during rmmod.
Init_nodule initializes some drivers during execution. The most important work is three.
Device: register the device, apply for the IP address range of the I/O port, and apply for the IRQ interruption. Here, only
You have registered a device.

The following is a typical init_module function:

Int init_module (void ){
Int result = check_region (short_base, 1);/* view the port address */
......
Request_region (short_base, 1, "short");/* apply for a port address */
......
Result = register_chrdev (short_major, "short", & short_fops);/* register the device
*/
......
Result = request_irq (short_irq, short_interrupt, SA_INTERRUPT, "short ",
NULL);/* apply for IRQ */
......
Return 0;
}/* Init_module */

I only keep the most important part of the above function. The most important function is
Result = register_chrdev (short_major, "short", & short_fops );
This is the essence of a driver !! When you execute the indmod command, this function can accomplish three major tasks:
First, apply for the master device number (short_major), or specify, or dynamically allocate; second, register the settings in the kernel
Backup name ("short"); third, specify the fops method (& short_fops ). The specified fops method is
How can we perform operations on devices (such as read, write, seek, dir, open, and release )?
These methods are most of the work to compile the device driver.

Now we need to get into the key part-how to implement the fops method.
We all know that each file has a file structure, in which there is a file_operations
Struct, which specifies the operations that can be performed on the file.

The following is a typical file_operations structure:
Struct file_operations {
Loff_t (* llseek) (struct file *, loff_t, int );
Ssize_t (* read) (struct file *, char *, size_t, loff_t *);
Ssize_t (* write) (struct file *, const char *, size_t, loff_t *);
Int (* readdir) (struct file *, void *, filldir_t );
Unsigned int (* poll) (struct file *, struct poll_table_struct *);
Int (* ioctl) (struct inode *, struct file *, unsigned int, unsigned
Long );
Int (* mmap) (struct file *, struct vm_area_struct *);
Int (* open) (struct inode *, struct file *);
Int (* flush) (struct file *);
Int (* release) (struct inode *, struct file *);
Int (* fsync) (struct file *, struct dentry *);
Int (* fasync) (int, struct file *, int );
Int (* check_media_change) (kdev_t dev );
Int (* revalidate) (kdev_t dev );
Int (* lock) (struct file *, int, struct file_lock *);
};

We can see that it is actually a function pointer for many file operations, where there is write, and we will not
Ignore it. This write pointer will appear in the actual driver by the name of the function implemented by the programmer.
The device write operation function implemented by the programmer. The following is an actual example. This write function can forward
Input a string in an array of memory.

Int short_write (struct inode * inode, struct file * filp, const char * buf,
Int count ){
Int retval = count;
Extern unsigned char kbuf [10];

If (count> 10)
Count = 10;
Copy_from_user (kbuf, buf, count );
Return retval;
}/* Short_write */
The fops method corresponding to the device short_t is declared as follows:
Struct file_operations short_fops = {
NULL,/* short_lseek */
Short_read,
Short_write,
NULL,/* short_readdir */
NULL,/* short_poll */
NULL,/* short_ioctl */
NULL,/* short_mmap */
Short_open,
Short_release,
NULL,/* short_fsync */
NULL,/* short_fasync */
/* Nothing more, fill with NULLs */
};

The NULL project does not provide this function. So we can see that the short_t device only provides
Read, write, open, and release functions. Here, we have implemented the write function above. The specific implementation function
The number is named short_write. These functions are the functions that actually operate on the device.
Good news: no matter how complicated your implementation is, but for users, it is common file operation functions.

However, we can see that the write function in the driver has four parameters. The function format is as follows:
Short_write (struct inode * inode, struct file * filp, const char * buf, int count)
The write function in your program has only three parameters. The function format is as follows:
Write (inf fd, char * buf, int count)
How are the two of them linked together? This depends on the function sys_write in the core of the operating system. below
Source code in sys_write in Linux Kernel 2.2.14:
Asmlinkage ssize_t sys_write (unsigned int fd, const char * buf, size_t count)
{
Ssize_t ret;
Struct file * file;
Struct inode * inode;
Ssize_t (* write) (struct file *, const char *, size_t, loff_t *);/* points
Pointer to the wirte function in the driver */

Lock_kernel ();
Ret =-EBADF;
File = fget (fd);/* get the file pointer through the file descriptor */
If (! File)
Goto bad_file;
If (! (File-> f_mode & FMODE_WRITE ))
Goto out;
Inode = file-> f_dentry-> d_inode;/* Get inode information */
Ret = locks_verify_area (FLOCK_VERIFY_WRITE, inode, file, file-> f_pos,
Count );
If (ret)
Goto out;
Ret =-EINVAL;
If (! File-> f_op |! (Write = file-> f_op-> write)/* declare
The write function pointer points to the corresponding write function in the fops Method */
Goto out;
Down (& inode-> I _sem );
Ret = write (file, buf, count, & file-> f_pos);/* use the write function in the driver
Input the data to the device. Note that there are four parameters */
Up (& inode-> I _sem );
Out:
Fput (file );
Bad_file:
Unlock_kernel ();
Return ret;
}

I wrote a simple program to test this driver. The source code of this program is excerpted as follows (I have saved all the provinces ):

Main (){
Int fd, count = 0;
Unsigned char buf [10];
Fd = open ("/dev/short_t", O_RDWR );
Printf ("input string :");
Scanf ("% s", buf );
Count = strlen (buf );
If (count> 10)
Count = 10;
Count = write (fd, buf, count );
Close (fd );
Return 1;
}

Now we will demonstrate how the user writes data to the device using the write function:
1. insmod driver. The driver requests the device name and master device number, which can be obtained in/proc/devieces.
2. Obtain the master device number from/proc/devices and run the mknod command to create a device node file. This is through the master
The device number associates the device node file with the device driver. The file attribute in the device node file indicates
Function pointer implemented by the fops method in the driver.
3. the user program uses open to open the device node file. When the operating system kernel knows that the driver is working
Call the open function in the fops Method for corresponding work. The open method generally returns a file identifier.
It does not directly operate on it, but the operating system calls work behind the scenes.
4. When you use the write function to operate a device file, the operating system calls the sys_write function.
The inode pointer and flip pointer corresponding to the device node file are obtained through the file identifier. The inode pointer contains a device ID.
To tell the operating system which device driver should be used. The flip pointer contains fops information and can tell
The corresponding fops method functions of the operating system can be found there.
5. Then, sys_write will call the write method in the driver to write the device.
Among them, 1-3 is performed in the user space, and 4-5 is performed in the core space. User's write function and Operating System
The write function of is linked by calling sys_write.
Note:
For Block devices, there is still a write mode problem, which should be solved by the gnu c library.
Because I have not read the source code of the GNU C library.
In addition, this is a beta version article. Please give your comments and suggestions. Thank you very much!

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.