Linux device driver Seventh: Blocking IO for advanced character driven operation

Source: Internet
Author: User

We've introduced a simple read,write operation before, so there's a problem: What if the driver doesn't respond to the request immediately? For example, a process call read read data, when there is no data to read what to do, whether to return immediately or wait until there is data, the other case is the process call write to the device, if the buffer is full or when the device is busy, to return or continue to wait until the device is writable? In this case, the general default practice is to keep the process asleep until the request is satisfied. This article describes how to deal with this type of problem-driven approach.

Sleep

What is sleep? A process sleep means that it temporarily abandons the CPU's power until a certain condition occurs before it can be dispatched again by the system.

It's easy to get a process into sleep in the drive, but there are a few rules that require special attention.

    1. Atomic context cannot sleep. This means that the drive cannot sleep while holding a spin lock, Seqlock, or RCU lock.
    2. Do not sleep in the case of an interrupt shutdown. You cannot sleep in an interrupt handler function.
    3. You can sleep while you are holding a semaphore, but it will cause other waiting processes to go to sleep, so pay special attention to the short sleep time.
    4. After being awakened you should do some necessary checks to make sure that the conditions you are waiting for are satisfied. Because you don't know what's going on during this time of sleep.
    5. Be sure to wake up before sleep, otherwise do not sleep.
How to sleep and wake up

The sleep process enters the waiting queue, and a wait queue can be declared as follows:

Declare_wait_queue_head (name);
Or dynamically, as follows:

wait_queue_head_t My_queue;
Init_waitqueue_head (&my_queue);

When a process needs to sleep, the following interfaces can be called:

The process is set to sleep without interruption, generally do not do so wait_event (queue, condition)//It may be interrupted by the signal, this version should check the return value, if the return non-zero may be interrupted by some signals, the driver should// The return-erestartsys.wait_event_interruptible (queue, condition)//below two waits for a period of time, after the timeout returns 0.wait_event_timeout (queue, condition, timeout) wait_event_interruptible_timeout (queue, condition, timeout)

To wake the dormant process, the other process calls the Wake function:

The following function wakes all the processes waiting on a given queue, typically paired with interruptible, without//paired with void Wake_up (wait_queue_head_t *queue); void Wake_up_ Interruptible (wait_queue_head_t *queue);
Blocking and non-blocking options

It said that the method of sleep, this implementation is blocking IO implementation, there is also a situation is to require whether the IO is available, the call to return immediately, is a non-blocking implementation. For example read, although there is no data to read, but I do not want to wait, I want to return immediately.

The non-blocking IO is indicated by the O_NONBLOCK flag in the Filp->f_flags, which is located in <linux/fcntl.h>, and is automatically included by <linux/fs.h>. This flag can be specified at open.

The default state of Io is blocked (without specifying O_nonblock), and the following criteria are required when implementing Read/write:

    • If a process calls read but no data is available (not yet), the process must be blocked. This process is immediately awakened when data is reached, and that data is returned to the caller, even if it is less than the number requested in the count parameter to the method.
    • If a process calls write and there is no space in the buffer, the process must be blocked and it must be in a different wait queue that is used as read. When some data is written to the hardware device and the space in the output buffer becomes idle, the process is woken up and the write call succeeds, although the data may only be partially written if there is only no space in the buffer to give the requested count bytes.

Both of these words assume that there are input and output buffers, and in fact, almost every device driver has an input-output buffer. Buffering improves access efficiency and prevents data loss.

If you specify O_nonblock, that is, non-blocking access. The practice of read and write is different. In this case, these calls simply return-eagain. Only Read,write and open file operations receive the effect of non-blocking flags.

The following is a simple read implementation that is compatible with blocking and non-blocking implementations (key places to add comments):

Static ssize_t scull_p_read (struct file *filp, char __user *buf, size_t count, loff_t *f_pos) {struct Scull_pipe *        dev = filp->private_data;        if (down_interruptible (&dev->sem)) Return-erestartsys; while (DEV-&GT;RP = = DEV-&GT;WP) {/* Nothing to read */Up (&AMP;DEV-&GT;SEM);/* Release the lock *                ///To determine if it is blocking access, and if it is non-blocking, return-eagain immediately.                if (Filp->f_flags & O_nonblock) Return-eagain;                 Pdebug ("\"%s\ "reading:going to Sleep\n", Current->comm);                If it is blocking access, then sleep waits until the read condition is met to continue execution. if (Wait_event_interruptible (DEV-&GT;INQ, (dev->rp! = dev->wp))) Return-erestartsys; /* Signal:tell the FS layer to handle it */* otherwise loop, but first reacquire the lock */if (down_in        Terruptible (&dev->sem)) Return-erestartsys; }/* OK, data is there,return something *///The data is read normally.        if (Dev->wp > Dev->rp) Count = Min (count, (size_t) (DEV-&GT;WP-DEV-&GT;RP)); else/* The write pointer have wrapped, return data up to Dev->end */count = min (count, (size_t) (Dev-&gt        ; end-dev->rp));                if (Copy_to_user (buf, DEV-&GT;RP, Count)) {up (&AMP;DEV-&GT;SEM);        Return-efault;        } DEV-&GT;RP + = count; if (DEV-&GT;RP = = dev->end) DEV-&GT;RP = dev->buffer;        /* Wrapped */up (&AMP;DEV-&GT;SEM);        /* Finally, awake any writers and return */wake_up_interruptible (&AMP;DEV-&GT;OUTQ);        Pdebug ("\"%s\ "did read%li bytes\n", Current->comm, (long) count); return count;}
Mutex wait

We said before that, when a process calls WAKE_UP, all the waiting processes on this queue are set to run. In general this is not a problem, but in an individual case, it may be known in advance that only one of the awakened processes will succeed in obtaining the required resources, and the other processes will sleep again. If there are too many processes waiting, all waking up to sleep is also resource-intensive and can degrade the performance of the system. To cope with this situation, a mutually exclusive wait option has been added to the kernel. As a result, the process of mutually exclusive waits is awakened one at a time.

Mutual exclusion waits under normal circumstances, so it is no longer concerned.

For the time being, the next article continues to look at some of the other advanced character driven operations Poll/select.

Before the series of articles like below, welcome to read attention:

Linux device driver First article: Introduction to device drivers

Linux Device driver Second article: Building and running modules

Linux Device driver Third article: write a simple character device driver

Linux Device driver Fourth: A case study of the Oops Information positioning code behavior the driving debugging method

Linux device driver Fifth: Concurrency and the state of drive

Linux Device driver Sixth: Iotcl of advanced character driven operation

This article is original, reproduced please indicate the source, offenders must investigate

Focus on the public platform: the Programmer Interaction Alliance (coder_online), you can get the first original technical articles, and (Java/c/c++/android/windows/linux) technology Daniel Friends, online communication programming experience, get programming basics, Solve programming problems. Programmer Interactive Alliance, Developer's own home.

Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.

Linux device driver Seventh: Blocking IO for advanced character driven operation

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.