Введение | В Linux процессы, которые ждут только процессорного времени, называются готовыми процессами. Они помещаются в очередь выполнения, а флаг состояния готового процесса — TASK_RUNNING. Как только временной интервал запущенного процесса будет исчерпан, планировщик ядра Linux лишит процесс контроля над ЦП и выберет для запуска подходящий процесс из очереди выполнения. |
Конечно, процесс также может активно освобождать контроль над процессором. Функция Schedule() — это функция планирования, которая может активно вызываться процессом для планирования использования ЦП другими процессами. Как только процесс, который добровольно отказывается от ЦП, перепланирован, чтобы занять ЦП, он начнет выполнение с того места, где он остановился в последний раз, то есть он начнет выполнение со следующей строки кода, которая вызывает Schedule().
Иногда процессу необходимо дождаться определенного события, например инициализации устройства, завершения операции ввода-вывода или истечения срока действия таймера. В этом случае процесс необходимо удалить из очереди выполнения и добавить в очередь ожидания.В это время процесс переходит в состояние сна.
Один из них — прерываемый режим сна, его флаг состояния — TASK_INTERRUPTIBLE;
Другой — это состояние непрерывного сна, и его флаг состояния — TASK_UNINTERRUPTIBLE. Процесс в состоянии прерываемого сна будет спать до тех пор, пока не станет истинным определенное условие. Например, условиями для пробуждения процесса могут быть генерация аппаратного прерывания, освобождение системных ресурсов, которых ожидает процесс, или доставка сигнала. Состояние непрерывного сна похоже на состояние прерываемого сна, но имеет одно исключение: процесс, доставляющий сигнал в это состояние сна, не может изменить свое состояние, то есть не реагирует на сигнал о пробуждении. Состояние непрерывного сна обычно используется реже, но оно все же очень полезно в некоторых конкретных ситуациях.Например, процесс должен ждать и не может быть прерван до тех пор, пока не произойдет определенное событие.
В современных операционных системах Linux процессы обычно переходят в состояние сна путем вызова метода Schedule(). Следующий код выполняет
показывает, как перевести запущенный процесс в спящий режим.
Sleep_task = текущий;
set_current_state(TASK_INTERRUPTIBLE);
расписание();
func1();
/* Остальная часть кода... */
В первом операторе программа сохраняет указатель структуры процесса Sleep_task, текущий — макрос, указывающий на исполняемый процесс
структура процесса. set_current_state() изменяет состояние процесса с состояния выполнения TASK_RUNNING на состояние сна
TASK_INTERRUPTIBLE. Если функция Schedule() запланирована процессом со статусом TASK_RUNNING, то функция Schedule() запланирует занятие ЦП другим процессом; если функция Schedule() запланирована процессом со статусом TASK_INTERRUPTIBLE или TASK_UNINTERRUPTIBLE, то необходимо выполнить дополнительный шаг Выполняется: выполняющийся в данный момент процесс будет удален из очереди выполнения до того, как будет запланирован другой процесс, что приведет к переходу работающего процесса в спящий режим, поскольку он больше не находится в очереди выполнения.
Мы можем использовать следующую функцию, чтобы разбудить процесс, который только что заснул.
пробуждение_up_process(спящая_задача);
После вызоваake_up_process() статус спящего процесса будет установлен на TASK_RUNNING, а планировщик
Он будет добавлен в очередь выполнения. Разумеется, этот процесс можно будет запустить только в следующий раз, когда он будет запланирован планировщиком.
Почти во всех случаях процесс переходит в спящий режим после проверки определенных условий и обнаружения, что они не выполняются. Но иногда
Однако процесс перейдет в спящий режим после того, как условие принятия решения станет истинным. В этом случае процесс будет спать бесконечно. Это так называемая проблема недействительного пробуждения. В операционной системе, когда несколько процессов пытаются выполнить некоторую обработку общих данных, а конечный результат зависит от порядка запуска процессов, возникает состояние гонки. Это типичная проблема в операционной системе. вверх Именно из-за конкурентных условий.
Предположим, есть два процесса A и B. Процесс A обрабатывает связанный список. Ему необходимо проверить, пуст ли связанный список. Если он не пуст, обработать ссылку
Данные в таблице подвергаются некоторым операциям, а процесс B также добавляет узлы в связанный список. Когда связанный список пуст из-за отсутствия данных для работы, процесс A переходит в спящий режим. Когда процесс B добавляет узел в связанный список, он пробуждает процесс A. Код следующий:
Процесс:
1 spin_lock(&list_lock);
2 if(list_empty(&list_head)) {
3 spin_unlock(&list_lock);
4 set_current_state(TASK_INTERRUPTIBLE);
5 расписание();
6 spin_lock(&list_lock);
7}
8
9 /* Остальная часть кода... */
10 spin_unlock(&list_lock);
Процесс Б:
100 spin_lock(&list_lock);
101 list_add_tail(&list_head, new_node);
102 spin_unlock(&list_lock);
103 Wake_up_process(process_task);
Здесь будет проблема: если процесс A выполняется после строки 3 и перед строкой 4, процесс B запланирован другим процессором
введен в эксплуатацию. В течение этого интервала времени процесс B выполнил все свои инструкции, поэтому он пытается разбудить процесс A. В это время процесс A еще не перешел в спящий режим, поэтому операция пробуждения недействительна. После этого процесс A продолжает выполняться. Он ошибочно подумает, что связанный список в это время еще пуст, поэтому устанавливает его статус в TASK_INTERRUPTIBLE, а затем вызывает Schedule(), чтобы перейти в спящий режим. Поскольку процесс B пропустил вызов пробуждения, он будет спать неопределенное время. Это проблема недопустимого пробуждения, поскольку процесс A все еще спит, даже если в связанном списке есть данные, которые необходимо обработать.
Как избежать проблем с неверным пробуждением? Мы обнаружили, что недействительные пробуждения в основном происходят после проверки условий и перехода процесса в состояние сна
Перед состоянием функция Wake_up_process() процесса B изначально предоставляла возможность установить состояние процесса A на TASK_RUNNING. К сожалению, состояние процесса A в это время все еще было TASK_RUNNING, поэтому Wake_up_process() изменил состояние процесса A из спящего режима. состояние в рабочее состояние.Попытки не дали желаемого эффекта. Чтобы решить эту проблему, необходимо использовать механизм гарантии, чтобы определение того, что связанный список пуст, и перевод состояния процесса в спящее состояние стало неотъемлемым шагом. ( ) может играть роль пробуждения процесса, находящегося в спящем состоянии.
Найдя причину, измените структуру кода процесса A, чтобы избежать проблемы недопустимого пробуждения в приведенном выше примере.
Процесс:
1 set_current_state(TASK_INTERRUPTIBLE);
2 spin_lock(&list_lock);
3 if(list_empty(&list_head)) {
4 spin_unlock(&list_lock);
5 расписание();
6 spin_lock(&list_lock);
7}
8 set_current_state(TASK_RUNNING);
9
10 /* Остальная часть кода... */
11 spin_unlock(&list_lock);
Как видите, этот код устанавливает текущее состояние процесса выполнения на TASK_INTERRUPTIBLE перед проверкой условий и устанавливает себя в состояние TASK_RUNNING, когда связанный список не пуст. Таким образом, если процесс B находится в процессе A, проверка процесса
После вызова Wake_up_process() после того, как связанный список пуст, статус процесса A автоматически изменится с исходного TASK_INTERRUPTIBLE
Он становится TASK_RUNNING.После этого, даже если процесс снова вызовет Schedule(), так как его текущий статус TASK_RUNNING, он все равно не будет удален из очереди выполнения, поэтому он не перейдет в сон по ошибке, и конечно, проблема недействительного пробуждения можно избежать.
In the Linux operating system, the stability of the kernel is crucial. In order to avoid invalid wake-up problems in the Linux operating system kernel,
The Linux kernel should use operations similar to the following when it needs to sleep a process:
/* ‘q’ is the waiting queue we want to sleep in */
DECLARE_WAITQUEUE(wait,current);
add_wait_queue(q, &wait);
set_current_state(TASK_INTERRUPTIBLE);
/* or TASK_INTERRUPTIBLE */
while(!condition) /* ‘condition’ is the waiting condition*/
schedule();
set_current_state(TASK_RUNNING);
remove_wait_queue(q, &wait);
The above operation allows the process to safely add itself to a waiting queue for sleep through the following series of steps: first adjust
Use DECLARE_WAITQUEUE () to create a waiting queue item, then call add_wait_queue() to add yourself to the waiting queue, and set the status of the process to TASK_INTERRUPTIBLE or TASK_INTERRUPTIBLE. Then the loop checks whether the condition is true: if it is, there is no need to sleep, if the condition is not true, schedule() is called. When the conditions checked by the process are met, the process sets itself to TASK_RUNNING and calls remove_wait_queue() to remove itself from the waiting queue.
As you can see from the above, the Linux kernel code maintainer also sets the state of the process to sleep state before the process checks the conditions,
Then the loop checks the condition. If the condition has been met before the process starts sleeping, then the loop will exit and use set_current_state() to set its state to ready. This also ensures that the process will not have the tendency to enter sleep by mistake, and of course it will not cause an error. Invalid wakeup problem.
Let us use an example in the Linux kernel to see how the Linux kernel avoids invalid sleep. This code comes from the Linux 2.6 kernel (linux-2.6.11/kernel/sched.c: 4254):
4253 /* Wait for kthread_stop */
4254 set_current_state(TASK_INTERRUPTIBLE);
4255 while (!kthread_should_stop()) {
4256 schedule();
4257 set_current_state(TASK_INTERRUPTIBLE);
4258 }
4259 __set_current_state(TASK_RUNNING);
4260 return 0;
The above codes belong to the migration service thread migration_thread. This thread continuously checks kthread_should_stop(),
It cannot exit the loop until kthread_should_stop() returns 1, which means that the process will sleep as long as kthread_should_stop() returns 0. We can see from the code that the check kthread_should_stop() is indeed executed after the process status is set to TASK_INTERRUPTIBLE. Therefore, if another process attempts to wake it up after the condition check but before schedule(), the wake-up operation of the process will not be invalidated.
Through the above discussion, we can find that the key to avoid invalid wake-up of the process in Linux is to
The status is set to TASK_INTERRUPTIBLE or TASK_UNINTERRUPTIBLE, and if the checked conditions are met, it should
Reset its status to TASK_RUNNING. In this way, no matter whether the waiting conditions of the process are met or not, the process will not enter the sleep state by mistake because it is removed from the ready queue, thereby avoiding the problem of invalid wake-up.
The above is the detailed content of Master teaches you how to set up the sleep and wake-up of Linux processes. For more information, please follow other related articles on the PHP Chinese website!

linux设备节点是应用程序和设备驱动程序沟通的一个桥梁;设备节点被创建在“/dev”,是连接内核与用户层的枢纽,相当于硬盘的inode一样的东西,记录了硬件设备的位置和信息。设备节点使用户可以与内核进行硬件的沟通,读写设备以及其他的操作。

区别:1、open是UNIX系统调用函数,而fopen是ANSIC标准中的C语言库函数;2、open的移植性没fopen好;3、fopen只能操纵普通正规文件,而open可以操作普通文件、网络套接字等;4、open无缓冲,fopen有缓冲。

端口映射又称端口转发,是指将外部主机的IP地址的端口映射到Intranet中的一台计算机,当用户访问外网IP的这个端口时,服务器自动将请求映射到对应局域网内部的机器上;可以通过使用动态或固定的公共网络IP路由ADSL宽带路由器来实现。

在linux中,交叉编译是指在一个平台上生成另一个平台上的可执行代码,即编译源代码的平台和执行源代码编译后程序的平台是两个不同的平台。使用交叉编译的原因:1、目标系统没有能力在其上进行本地编译;2、有能力进行源代码编译的平台与目标平台不同。

在linux中,eof是自定义终止符,是“END Of File”的缩写;因为是自定义的终止符,所以eof就不是固定的,可以随意的设置别名,linux中按“ctrl+d”就代表eof,eof一般会配合cat命令用于多行文本输出,指文件末尾。

在linux中,可以利用“rpm -qa pcre”命令判断pcre是否安装;rpm命令专门用于管理各项套件,使用该命令后,若结果中出现pcre的版本信息,则表示pcre已经安装,若没有出现版本信息,则表示没有安装pcre。

linux查询mac地址的方法:1、打开系统,在桌面中点击鼠标右键,选择“打开终端”;2、在终端中,执行“ifconfig”命令,查看输出结果,在输出信息第四行中紧跟“ether”单词后的字符串就是mac地址。

在linux中,rpc是远程过程调用的意思,是Reomote Procedure Call的缩写,特指一种隐藏了过程调用时实际通信细节的IPC方法;linux中通过RPC可以充分利用非共享内存的多处理器环境,提高系统资源的利用率。


Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

AI Hentai Generator
Generate AI Hentai for free.

Hot Article

Hot Tools

WebStorm Mac version
Useful JavaScript development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

SublimeText3 Chinese version
Chinese version, very easy to use

Safe Exam Browser
Safe Exam Browser is a secure browser environment for taking online exams securely. This software turns any computer into a secure workstation. It controls access to any utility and prevents students from using unauthorized resources.

Dreamweaver Mac version
Visual web development tools
