Concurrency Control for Linux kernel development (4)

Source: Internet
Author: User

Output Table 7: semaphores (semaphores are actually the same as spin locks, that is, they are a little different: When the semaphores are not obtained, the process does not repeat in the same place but enters the sleep waiting state)

In Linux, there are four main semaphore-related operations:

1) define the semaphore struct semaphore sem;

2) initialize the semaphore

Void sema_init (struct semphore * sem, int val); // set sem to val

Void init_MUTEX (struct semaphore * sem); // initialize a mutex semaphores. sem is set to 1.

Void init_MUTEX_LOCKED (struct semaphore * sem); // initialize a mutex semaphores. The sem value is set to 0.

DECLARE_MUTEX (name); // This macro defines the semaphore name and initializes 1

DECLARE_MUTEX_LOCKED (name); // This macro defines the semaphore name and initializes 0

3) obtain the semaphore

Void down (struct semaphore * sem); // This function is used to obtain semaphores sem, which can cause sleep and cannot be interrupted by signals, so it cannot be used in the interrupt context.

Int down_interruptible (struct semaphore * sem); // This function is returned because the sleeping process can be interrupted by a signal.

Int down_trylock (struct semaphore * sem); // try to obtain the semaphores sem. If yes, get and return 0; otherwise, return non-0, which does not cause the caller to sleep, can be used in interrupt Context

Generally

If (down_interruptible (& sem ))

{

Return-ERESTARTSYS;

}

4) Release semaphores

Void up (struct semaphore * sem); // release semaphores sem to wake the waiting person

Semaphores are generally used as follows:

// Defines the semaphore.

DECLARE_MUTEX (mount_sem );

Down (& mount_sem); // obtain the semaphore to protect the critical section

...

Critical section // critical section

...

Up (& mount_sem );

Now, let's take an example to see how to use semaphores to enable a device only by one process:

Static DECLARE_MUTEX (xxx_lock); // defines the mutex.

Static int xxx_open (struct inode * inode, struct file * filp)

{

...

If (down_trylock (& xxx_lock) // obtain the unlock lock

Return-EBUSY; // The device is busy.

...

Return 0; // success

}

 

Static int xxx_release (struct inode * inode, struct file * filp)

{

Up (& xxx_lock); // release the unlock lock

Return 0;

}

In the above-mentioned operations on semaphores, we mentioned a problem that is the semaphores initialization. Generally, there is no limit on semaphores initialization, but if the semaphores are initialized to 0, it can be used for synchronization. Here, we have to introduce a new trick.

 

Output Table 8: synchronization (it means that the execution of one execution unit needs to wait for another Execution Unit to complete its tasks, ensuring the execution order)

In this figure, before execution unit A executes code Area B, it is necessary to wait for Execution Unit B to execute code Unit c, and the semaphore can help to complete this synchronization process.

 

At this time, you may ask, synchronization like this is often encountered in reality. for example, you must wait for the previous one to complete the last one .. wait, is it a synchronization method ..

Haha, it's really smart. The little dish has finally grown up and become a big dish. in fact, the Linux system provides a better synchronization mechanism-the amount of completion. Well, if you are eager to study, it will be passed to you together, no charge.

Table 9: completion, which is used for one execution unit to wait for another execution unit to finish

Usage: 1) define the completion volume

Struct completion my_completion;

2) initialization

Init_completion (& my_completion); // If you find these two steps troublesome, you will be given a macro to define and initialize DECLARE_COMPLETION (my_completion );

3) waiting for completion

Void wait_for_completion (structcompletion * c); // wait for a completion to be awakened

Wait_for_completion_interruptible (struct completion * c); // wait_for_completion

Unsigned long wait_for_completion_timeout (struct completion * x, unsigned long timeout); // wait_for_completion with timeout

4) Number of wake-up completions

Void complete (struct completion * c); // wake up only one waiting execution unit.

Void complete_all (struct completion * c); // wake up all execution units waiting for this completion

If I have said so much about this memory, how can I forget to provide the completion structure:

Struct completion

{

Unsigned int done; // indicates whether it has been completed. If it is not finished, It is a negative value, indicating the number of waits. The value is 0.

Wait_queue_head_t wait;

}

If you do not understand it or are not addicted to it, I will give you a picture:

How is this feeling? Much better...

To be honest, I didn't even think it would take so long. Although I don't want to, I can only say: Let's talk about things later ..

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.