Implementation of data storage and read/write synchronization in a device-driven central buffer zone

Source: Internet
Author: User

First, we define several basic pointers and parameters for the buffer zone through custom data structures:

Char * buffer_start, * buffer_end points to the start and end pointers of the buffer.

Char * WP, * RP data read/write pointer

Int buffersize buffer size

Call the kmalloc function of the memory allocation function to apply for memory space for the data structure. After initialization, the data read and write pointers all point to char * buffer_star. For the buffer zone, we can perform a few rules:

1. * Wp = * RP: The data buffer is empty. In this case, the read operation should be blocked, no data is readable, And the read process enters the sleep waiting state. For write operations, write sleep will be awakened, the write size is the size of the entire buffer space.

2. * WP> * RP: the buffer zone contains readable data. The read size is WP-RP, And the read process is not blocked. When WP-Rp = buffersize, the write process is blocked and goes to sleep, if WP-rp <buffersize, the write process will not be blocked, and there is still space for writing in the buffer.

3. * WP <* RP: If wp rp points to buffer_end, it will be automatically reversed to the buffer_start position, writable space for the rp-wp-1

Through the blocking and sleep mechanisms, we can synchronize read and write of this buffer. The following Code explains the principles of Read and Write synchronization:

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) Lock the semaphore
Return-erestartsys;

While (Dev-> Rp = Dev-> WP) {/* nothing to read */at this time, the buffer is empty and no data is readable.
Up (& Dev-> SEM);/* release the lock * // * unlock semaphores. Note: The semaphores must be unlocked before the sleep is blocked */
If (filp-> f_flags & o_nonblock)
Return-eagain;
Pdebug ("/" % S/"reading: Going to sleep/N", current-> comm );
If (wait_event_interruptible (Dev-> INQ, (Dev-> RP! = Dev-> WP)/* blocking, enter sleep, when Dev-> RP! = Dev-> when the WP condition is met, wake up to sleep. This sleep should be awakened during write operations */
Return-erestartsys;/* signal: Tell the FS layer to handle it */
/* Otherwise loop, but first reacquire the lock */
If (down_interruptible (& Dev-> SEM)/* if awakened, re-lock the semaphore for Data Reading */
Return-erestartsys;
}
/* OK, data is there, return something */
If (Dev-> WP> Dev-> RP)
Count = min (count, (size_t) (Dev-> WP-Dev-> RP ));
Else/* The write pointer has wrapped, return data up to Dev-> end */
Count = min (count, (size_t) (Dev-> end-Dev-> RP ));
If (copy_to_user (BUF, Dev-> RP, count) {/* I in the case of rp> WP, this operation cannot read all the data in the buffer at a time */
Up (& Dev-> SEM);/* It must be read twice. Read-only to end-RP for the first time and WP-start for the second time */
Return-efault;
}
Dev-> RP + = count;/* The Count value has been processed. Ensure that Dev-> RP + = count does not exceed buffer_end */

If (Dev-> Rp = Dev-> end)
Dev-> Rp = Dev-> buffer;/* Wrapped */
Up (& Dev-> SEM );

/* Finally, awake any writers and return */
Wake_up_interruptible (& Dev-> outq);/* update the pointer after reading ends to wake up writing sleep */
Pdebug ("/" % S/"did read % Li Bytes/N", current-> comm, (long) count );
Return count;
}

Static ssize_t scull_p_write (struct file * filp, const char _ User * Buf, size_t count,
Loff_t * f_pos)
{
Struct scull_pipe * Dev = filp-> private_data;
Int result;

If (down_interruptible (& Dev-> SEM ))
Return-erestartsys;

/* Make sure there's space to write */
Result = scull_getwritespace (Dev, filp);/* test whether there is space for writing */
If (result)
Return result;/* scull_getwritespace called up (& Dev-> SEM )*/

/* OK, space is there, accept something */
Count = min (count, (size_t) spacefree (Dev);/* If yes, check how much space can be written */
If (Dev-> WP> = Dev-> RP)
Count = min (count, (size_t) (Dev-> end-Dev-> WP )); /* To End-of-Buf * // * it seems that there is still a small space not written */
Else/* The write pointer has wrapped, fill up to RP-1 */
Count = min (count, (size_t) (Dev-> RP-Dev-> WP-1 ));
Pdebug ("going to accept % Li bytes to % P from % P/N", (long) count, Dev-> WP, Buf );
If (copy_from_user (Dev-> WP, Buf, count )){
Up (& Dev-> SEM );
Return-efault;
}
Dev-> WP + = count;
If (Dev-> Wp = Dev-> end)
Dev-> Wp = Dev-> buffer;/* Wrapped * // * update write pointer */
Up (& Dev-> SEM );

/* Finally, awake any reader */
Wake_up_interruptible (& Dev-> INQ);/* after writing, data must be readable and sleep */

/* And signal asynchronous readers, explained late in Chapter 5 */
If (Dev-> async_queue)
Kill_fasync (& Dev-> async_queue, sigio, poll_in );
Pdebug ("/" % S/"did write % Li Bytes/N", current-> comm, (long) count );
Return count;
}

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.