Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to understand Linux kernel semaphores

2025-03-25 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Servers >

Share

Shulou(Shulou.com)06/01 Report--

This article is about how to understand Linux kernel semaphores. I think it is very practical, so I share it with you. I hope you can get something after reading this article. Let's take a look at it.

Concept

The semaphore of the Linux kernel is the same in concept and principle as the IPC mechanism semaphore of System V in user mode, but it can never be used outside the kernel, so it has nothing to do with System V's IPC mechanism semaphore.

If a task wants to get an occupied semaphore, the semaphore puts it in a waiting queue (it doesn't stand outside and wait, but writes its name in the task queue) and puts it to sleep.

When the process holding the semaphore releases the signal, a task in the waiting queue will be awakened (because there may be more than one task in the queue) and let it get the semaphore. Unlike spin locks, the processor can execute other code.

Application scenario

Because processes contending for semaphores sleep while waiting for locks to become available again, semaphores are suitable for situations where locks will be held for a long time; on the contrary, it is not appropriate to use semaphores when locks are held for a short period of time, because the overhead of sleeping, maintaining wait queues, and waking up may be longer than the entire schedule occupied by locks.

Here are two examples from life:

It takes us 2 days to travel from Nanjing to Xinjiang by train. This' task'is particularly time-consuming, and we can only sit in the car and wait for the train to arrive, but we don't have to wait with our eyes open all the time. Ideally, we go to bed as soon as we get on the bus and wake up to the station (readers who have seen Alien will have a deep understanding). In this way, from the perspective of people (users), the experience is the best, compared with the process. When waiting for a time-consuming event, the program does not have to occupy the CPU all the time. It can pause the current task and put it into a dormant state, and then be awakened by other tasks after the waiting event occurs. Similar to this scenario, semaphores are more appropriate.

We sometimes wait for elevators and bathrooms, but it doesn't take much time to wait. If we have to find a place to sleep and then wait for the elevator to arrive or the bathroom can be used, it's obviously not necessary. We just need to line up and browse Douyin, compared with computer programs, such as drivers entering the interrupt routine, waiting for a register to be set. The waiting time for this scenario is often very short, and the system overhead is even much less than the cost of entering hibernation, so it is more appropriate to use spin lock in this scenario.

Semaphores and spin locks, as well as deadlocks, will be discussed in more detail later.

Usage

If a task wants to access shared resources, it must first get the semaphore, and the operation of obtaining the semaphore will subtract the value of the semaphore by 1. If the value of the current semaphore is negative, it indicates that the semaphore cannot be obtained. The task must suspend the waiting queue in the semaphore and wait for the semaphore to be available; if the value of the current semaphore is non-negative, it means that the semaphore can be obtained, so the shared resources protected by the semaphore can be accessed immediately.

When the task visits the shared resource protected by the semaphore, it must release the semaphore, which is realized by adding 1 to the value of the semaphore. If the value of the semaphore is non-positive, it indicates that there is a task waiting for the current semaphore. So he also wakes up all tasks waiting for the semaphore.

The composition of kernel semaphores

The kernel semaphore is similar to a spin lock in that it does not allow the kernel control path to continue when the lock is closed. However, when the kernel control path tries to obtain busy resources protected by kernel semaphore locks, the corresponding process is suspended. The process becomes runnable again only when the resource is released.

Only functions that can sleep can get kernel semaphores; neither interrupt handlers nor delayable functions can use kernel semaphores.

Kernel semaphores are objects of type struct semaphore and are located in the include\ linux\ semaphore.h file in the kernel source code

The struct semaphore {raw_spinlock_t lock; unsigned int count; struct list_head wait_list;} member describes the version of lock after 2.6.33. The kernel adds the raw_spin_lock series, using the same method as the spin_lock series, except that the parameter spinlock_t becomes the value of raw_spinlock_tcount equivalent to the semaphore, which is greater than 0, and the resource is idle. Equal to 0, the resource is busy, but no process is waiting for the protected resource; less than 0, the resource is not available, and there is at least one process waiting for the resource wait_list kernel linked list. The task that currently obtains the semaphore will register with the member in the waiting list.

API of semaphore

Initialization

DECLARE_MUTEX (name)

The macro declares a semaphore name and initializes its value to 1, which declares a mutex.

DECLARE_MUTEX_LOCKED (name)

The macro declares a mutex name, but sets its initial value to 0, which means that the lock is locked when it is created. Therefore, for this kind of lock, it is generally released before it is obtained.

Void sema_init (struct semaphore * sem, int val)

This function is used to initialize the initial value of the semaphore, which sets the value of the semaphore sem to val.

Note:

A val setting of 1 indicates that there is only one holder, and this semaphore is called a binary semaphore or mutex semaphore.

We also allow semaphores to have multiple holders, which are called counting semaphores. During initialization, we need to specify how many holders are allowed to initialize the val in the semaphore to any positive value n. In this case, at most n processes can access the resource concurrently.

Void init_MUTEX (struct semaphore * sem)

This function is used to initialize a mutex, that is, it sets the value of semaphore sem to 1.

Void init_MUTEX_LOCKED (struct semaphore * sem)

This function is also used to initialize a mutex, but it sets the value of the semaphore sem to 0, which means it is locked from the start.

PV operation

Get semaphore (P)

Void down (struct semaphore * sem)

This function is used to get the semaphore sem, which causes the process calling the function to sleep, so it cannot be used in interrupt contexts, including IRQ and softirq contexts. This function will subtract 1 from the value of sem and return directly if the semaphore sem is non-negative, otherwise the caller will be suspended until another task releases the semaphore.

Int down_interruptible (struct semaphore * sem)

The function is similar to down, except that down will not be interrupted by the signal (signal), but down_interruptible can be interrupted by the signal, so the function has a return value to distinguish whether it is returned normally or interrupted by the signal. If it returns 0, it means that the semaphore returns normally, and-EINTR is returned if it is interrupted by the signal.

Int down_trylock (struct semaphore * sem)

The function tries to get the semaphore sem, and if it can get it immediately, it gets the semaphore and returns 0; otherwise, it means that the semaphore sem cannot be obtained, and the return value is a non-zero value. Therefore, it does not cause the caller to sleep and can be used in the interrupt context.

Int down_killable (struct semaphore * sem); int down_timeout (struct semaphore * sem, long jiffies); int down_timeout_interruptible (struct semaphore * sem, long jiffies)

Release kernel semaphore (V)

Void up (struct semaphore * sem)

This function releases the semaphore sem, which adds 1 to the value of sem. If the value of sem is non-positive, it indicates that there is a task waiting for the semaphore, so wake up these waiters.

Supplement

Int down_interruptible (struct semaphore * sem)

The function of this function is to get the semaphore. if you don't get the semaphore, you sleep, and there is no signal interrupting, then go to sleep. However, it may be interrupted by a signal during sleep and return to-EINTR after the interruption, which is mainly used for mutually exclusive synchronization between processes.

Here are the comments for the function:

/ * * down_interruptible-acquire the semaphore unless interrupted * @ sem: the semaphore to be acquired * * Attempts to acquire the semaphore. If no more tasks are allowed to * acquire the semaphore, calling this function will put the task to sleep. * If the sleep is interrupted by a signal, this function will return-EINTR. * If the semaphore is successfully acquired, this function returns 0. , /

After a process calls down_interruptible (), if sem

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Servers

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report