How Linux write system calls are implemented

Source: Internet
Author: User
Tags goto

When we use the device under Linux, we use the Write function, which allows us to send data to the device as if it were a file. But why is it that the user can write data to the device using the Write function, and how is this process implemented?

This mystery lies in the write implementation of the device driver, where I combine some source code to explain how to make a simple write function complete the complex process of writing data to the device.

The source code here is mainly from two places. The first is the example of "Linux device Driver" published by OReilly, and the second is the Linux Kernel 2.2.14 core source code. I only list the relevant parts of the content, if the reader is interested, you can also check other source code. But I'm not explaining how to write a device driver, so I don't have to explain every detail, and there are places where I feel like I haven't thoroughly understand.

Since the examples in the book "Linux device Driver" are still a bit more complicated for us, I have simplified one of these routines. This driver supports such a device: An array of length 10 in the core space kbuf[10]. We can open it through the user program, read it, write it, close it. The name of this device I call short_t.

Let's do it now. For a device, it can have a corresponding logical device node in/dev, which exists as a file, but it is not a file in the ordinary sense, it is a device file, or rather it is a device node. This node is established with the Mknod command, which specifies the main device number and the secondary device number. The main device number indicates a certain type of device, which usually corresponds to a certain driver; the secondary device number is generally distinguished by distinguishing between different attributes, such as different usage methods, different positions, and different operations. This device number is obtained from the/proc/devices file, so there is usually a driver inside the kernel before the device node is in the directory. The main function of this device number (especially the main device number) is to declare the driver used by the device. The driver and device number is one by one, and when you open a device file, the operating system knows which driver the device corresponds to. This "know" process is followed.

Let's talk about the basic structure of the driver. Here I only introduce the dynamic module driver (that is, we use INSMOD to load into the core and use the Rmmod uninstall), 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 at the time of Insmod, while the latter is executed at Rmmod. Init_nodule is performing some driver initialization work, the most important of which is three
Devices: Register the device, request an I/O port address range, request an interrupt IRQ. This is related only to what we want to know.
There are registered devices.
The following is a typical Init_module function:
int Init_module (void) {
int result = Check_region (short_base,1);/* View port Address*/
......
Request_region (short_base,1, "short"); /* Request Port Address*/
......
result = Register_chrdev (Short_major, "short", &short_fops); /* Enroll Device
*/
......
result = Request_irq (SHORT_IRQ, Short_interrupt, Sa_interrupt, "short",
NULL); /*ApplicationIRQ */
......
return 0;
}/* init_module*/
I've only kept the most important part of the above function, the most important of which 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 things: first, request the main device number (short_major), or specify, or dynamically assign, second, register the name of the device in the kernel ("short"), and thirdly, specify the FoPs method (&short_ FoPs). The FoPs method that we specify is how we operate on the device (such as read,write,seek,dir,open,release, etc.), and how to implement these methods is where most of the work is done to write device drivers.

Now we are going to touch the key part-how to implement the FoPs method.As we all know, each document has a file structure, in which there is a file_operations structure that 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 to many file operations, in which there is write, and the rest of us will not take care of it. This write pointer appears in the actual driver as a function name implemented by the programmer, which points to the device write operation function implemented by the programmer. Here is a practical example of the write function that can enter a string into an array of core memory.

int short_write (struct inode *inode, struct file *filp, const char *BUF,
Int Co UNT) {
int retval = count;
extern unsigned char kbuf[10];

if (count>10)
count=10;
Copy_from_user (Kbuf, buf, Count);
return retval;
}/* short_write */
Device short_t The corresponding FoPs method is declared as follows:
struct File_operations Short_ FoPs = {
NULL,/* Short_lseek */
Short_read,
Short_write,
NULL,/* short_readdir */
NULL,/* Short_pol L/
NULL,/* SHORT_IOCTL */
NULL,/* short_mmap */
Short_open,
Short_release,
NULL,/* Short_fsync */
NULL,/* Short_fasync */
/Nothing more, fill with NULLs */
};

where NULL is a project that does not provide this functionality. So we can see that the short_t device only provides read,write,open,release functionality. Where the write function we have implemented above, the specific implementation function named Short_write. These functions are functions that really operate on the device, which is one of the great benefits of a driver: No matter how complex you are when you implement it, it's the usual file manipulation functions that users see.

but we can see that the write function in the driver has four parameters, and the function is in the following format:

Short_write (struct inode *inode, struct file *filp, const char *buf, int count) and the write function in the user program has only three parameters, the function is formatted as follows:

Write (INF fd, char *buf, int count)
So how do they relate to each other? This depends on the function sys_write in the core of the operating system, below
is the source code in the 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 *); /* point to
Pointers to Wirte functions 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))/* Declares the function at the beginning of the
WriteThe 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
Enter the data into the device, notice that this is 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 program source code excerpt is as follows (the province I have saved):

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 let's demonstrate how the user writes the data to the device using the Write function:
1,insmod driver. The driver requests the device name and the main device number, which can be obtained in/proc/devieces.
2, obtain the main device number from/proc/devices and use the Mknod command to set up the device node file. This is done through the main
device number Associate the device node file with the device driver. The file attribute in the device node files indicates the function pointer implemented by the FoPs method in the

3, the user program opens the device node file using open, when the operating system kernel knows that the driver is working, it
4, when the user uses the Write function to manipulate the device file, the operating system calls the Sys_write function, which first pass
The corresponding FoPs method function for the operating system can be found there. 5, and then Sys_write calls the Write method in the driver for writing to the device.
1-3 of them are in user space, 4-5 in the core space. The write function of a user and the write function of the operating system

Note:

In general: Device files are bundled with device drivers through the device number, and FoPs binds the write and drive layer of the application layer. When the application layer writes a device file, the system finds the corresponding device driver, and then finds the corresponding drive write function by FoPs.

How Linux write system calls are implemented

Related Article

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.