목차
无效唤醒" >无效唤醒
A进程:" >A进程:
B进程:" >B进程:
避免无效唤醒" >避免无效唤醒
Linux内核的例子" >Linux内核的例子
요약" >요약
시스템 튜토리얼 리눅스 Linux 프로세스의 절전 모드 해제 및 절전 모드

Linux 프로세스의 절전 모드 해제 및 절전 모드

Feb 10, 2024 pm 04:40 PM
linux 리눅스 튜토리얼 리눅스 시스템 리눅스 운영체제 리눅스 명령 쉘 스크립트 임베디드리눅스 리눅스 시작하기 리눅스 학습

Linux 시스템에서는 CPU 시간을 기다리는 프로세스만 준비 프로세스라고 합니다. 상태 플래그 TASK_RUNNING와 함께 실행 대기열에 배치됩니다. 실행 중인 프로세스가 해당 시간 조각을 모두 사용하면 Linux 커널 스케줄러는 CPU 제어권을 빼앗고 실행 대기열에서 실행할 적절한 프로세스를 선택합니다.

Linux 进程的唤醒和睡眠

물론 프로세스가 CPU 제어권을 적극적으로 포기할 수도 있습니다. schedule() 函数是一个调度函数,可以被进程主动调用,以便调度其他进程占用 CPU。一旦这个主动放弃 CPU 的进程重新被调度占用 CPU,它将从上次停止执行的位置开始执行,即从调用 schedule() 코드의 다음 줄이 실행을 시작합니다.

때때로 프로세스는 장치 초기화 완료, I/O 작업 완료 또는 타이머 만료와 같은 특정 이벤트가 발생할 때까지 기다려야 합니다. 이 경우 프로세스는 실행 큐에서 제거되고 대기 큐에 추가되어야 하며, 이 시점에서 프로세스는 절전 모드로 전환됩니다.

Linux에는 두 가지 프로세스 절전 상태가 있습니다.

  • 하나는 상태 플래그 TASK_INTERRUPTIBLE을 사용하는 인터럽트 가능한 절전 상태입니다.
  • 다른 하나는 중단할 수 없는 절전 상태이며 상태 플래그는 TASK_UNINTERRUPTIBLE입니다.

인터럽트 가능한 절전 상태의 프로세스는 특정 조건이 충족될 때까지 절전 모드로 유지됩니다. 예를 들어 하드웨어 인터럽트 발생, 프로세스가 기다리고 있는 시스템 리소스 해제 또는 신호 전달이 프로세스를 깨우는 조건이 될 수 있습니다. 무정전 슬립 상태는 인터럽트 가능 슬립 상태와 유사하지만 한 가지 예외가 있다. 즉, 이 슬립 상태에 신호를 전달하는 프로세스는 상태를 변경할 수 없다. 즉, 깨우라는 신호에 응답하지 않는다는 것이다. 중단 불가능한 절전 상태는 일반적으로 덜 사용되지만 일부 특정 상황에서는 여전히 매우 유용합니다. 예를 들어 프로세스는 특정 이벤트가 발생할 때까지 기다려야 하며 중단될 수 없습니다.

최신 Linux 운영 체제에서 프로세스는 일반적으로 schedule()를 호출하여 절전 상태로 전환됩니다. 다음 코드는 실행 중인 프로세스를 절전 상태로 전환하는 방법을 보여줍니다.

으아아아

첫 번째 명령문에서 프로그램은 프로세스 구조 포인터를 저장합니다. sleeping_taskcurrent는 실행 중인 프로세스 구조를 가리키는 매크로입니다.

set_current_state () 프로세스 상태를 실행 상태 set_current_state() 将该进程的状态从执行状态 TASK_RUNNING 变成睡眠状态 TASK_INTERRUPTIBLE。如果 schedule() 是被一个状态为 TASK_RUNNING 的进程调度,那么 schedule()에서 절전 상태 TASK_INTERRUPTIBLE.

가 🎜 상태의 프로세스에 의해 예약된 경우 🎜는 CPU를 점유하는 다른 프로세스를 예약합니다. 🎜

如果 schedule() 是被一个状态为 TASK_INTERRUPTIBLETASK_UNINTERRUPTIBLE 的进程调度,那么还有一个附加的步骤将被执行:当前执行的进程在另外一个进程被调度之前会被从运行队列中移出,这将导致正在运行的那个进程进入睡眠,因为它已经不在运行队列中了。

我们可以使用下面的这个函数将刚才那个进入睡眠的进程唤醒。

wake_up_process(sleeping_task);
로그인 후 복사

在调用了 wake_up_process() 以后,这个睡眠进程的状态会被设置为 TASK_RUNNING,而且调度器会把它加入到运行队列中去。当然,这个进程只有在下次被调度器调度到的时候才能真正地投入运行。

无效唤醒

几乎在所有的情况下,进程都会在检查了某些条件之后,发现条件不满足才进入睡眠。可是有的时候进程却会在判定条件为真后开始睡眠,如果这样的话进程就会无限期地休眠下去,这就是所谓的无效唤醒问题。

在操作系统中,当多个进程都企图对共享数据进行某种处理,而 最后的结果又取决于进程运行的顺序时,就会发生竞争条件,这是操作系统中一个典型的问题,无效唤醒恰恰就是由于竞争条件导致的。

设想有两个进程A 和B,A 进程正在处理一个链表,它需要检查这个链表是否为空,如果不空就对链表里面的数据进行一些操作,同时B进程也在往这个链表添加节点。当这个链表是空的时候,由于无数据可操作,这时A进程就进入睡眠,当B进程向链表里面添加了节点之后它就唤醒A 进程,其代码如下:

A进程:
1 spin_lock(&list_lock);
2 if (list_empty(&list_head)) {
3     spin_unlock(&list_lock);
4     set_current_state(TASK_INTERRUPTIBLE);
5     schedule();
6     spin_lock(&list_lock);
7 }
8
9 /* Rest of the code ... */
10 spin_unlock(&list_lock);
로그인 후 복사
B进程:
100 spin_lock(&list_lock);
101 list_add_tail(&list_head, new_node);
102 spin_unlock(&list_lock);
103 wake_up_process(processa_task);
로그인 후 복사

这里会出现一个问题,假如当A进程执行到第3行后第4行前的时候,B进程被另外一个处理器调度投入运行。在这个时间片内,B进程执行完了它所有的指令,因此它试图唤醒A进程,而此时的A进程还没有进入睡眠,所以唤醒操作无效。

在这之后,A 进程继续执行,它会错误地认为这个时候链表仍然是空的,于是将自己的状态设置为 TASK_INTERRUPTIBLE 然后调用 schedule() 进入睡 眠。由于错过了B进程唤醒,它将会无限期的睡眠下去,这就是无效唤醒问题,因为即使链表中有数据需要处理,A 进程也还是睡眠了。

避免无效唤醒

如何避免无效唤醒问题呢?

我们发现无效唤醒主要发生在检查条件之后和进程状态被设置为睡眠状态之前,本来B进程的 wake_up_process() 提供了一次将A进程状态置为 TASK_RUNNING 的机会,可惜这个时候A进程的状态仍然是 TASK_RUNNING,所以 wake_up_process() 将A进程状态从睡眠状态转变为运行状态的努力 没有起到预期的作用。

要解决这个问题,必须使用一种保障机制使得判断链表为空和设置进程状态为睡眠状态成为一个不可分割的步骤才行,也就是必须消除竞争条 件产生的根源,这样在这之后出现的 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     schedule();
6     spin_lock(&list_lock);
7 }
8 set_current_state(TASK_RUNNING);
9
10 /* Rest of the code ... */
11 spin_unlock(&list_lock);
로그인 후 복사

可以看到,这段代码在测试条件之前就将当前执行进程状态转设置成 TASK_INTERRUPTIBLE 了,并且在链表不为空的情况下又将自己置为 TASK_RUNNING 状态。

这样一来如果B进程在A进程进程检查了链表为空以后调用 wake_up_process(),那么A进程的状态就会自动由原来 TASK_INTERRUPTIBLE 变成 TASK_RUNNING,此后即使进程又调用了 schedule(),由于它现在的状态是 TASK_RUNNING,所以仍然不会被从运行队列中移出,因而不会错误的进入睡眠,当然也就避免了无效唤醒问题。

Linux内核的例子

在Linux操作系统中,内核的稳定性至关重要,为了避免在Linux操作系统内核中出现无效唤醒问题,Linux内核在需要进程睡眠的时候应该使用类似如下的操作:

/* q 是我们希望睡眠的等待队列 */
DECLARE_WAITQUEUE(wait, current);
add_wait_queue(q, &wait);
set_current_state(TASK_INTERRUPTIBLE);
/* condition 是等待的条件 */
while (!condition) {
    schedule();
}
set_current_state(TASK_RUNNING);
remove_wait_queue(q, &wait);
로그인 후 복사

上面的操作,使得进程通过下面的一系列步骤安全地将自己加入到一个等待队列中进行睡眠:首先调用 DECLARE_WAITQUEUE() 创建一个等待队列的项,然后调用 add_wait_queue() 把自己加入到等待队列中,并且将进程的状态设置为 TASK_INTERRUPTIBLE 或者 TASK_INTERRUPTIBLE

然后循环检查条件是否为真:如果是的话就没有必要睡眠,如果条件不为真,就调用 schedule()。当进程检查的条件满足后,进程又将自己设置为 TASK_RUNNING 并调用 remove_wait_queue() 将自己移出等待队列。

从上面可以看到,Linux的内核代码维护者也是在进程检查条件之前就设置进程的状态为睡眠状态,然后才循环检查条件。如果在进程开始睡眠之前条件就已经达成了,那么循环会退出并用 set_current_state() 将自己的状态设置为就绪,这样同样保证了进程不会存在错误的进入睡眠的倾向,当然也就不会导致出现无效唤醒问题。

下面让我们用 Linux 内核中的实例来看看其是如何避免无效睡眠的,这段代码出自 Linux2.6 的内核 (/kernel/sched.c):

/* Wait for kthread_stop */
set_current_state(TASK_INTERRUPTIBLE);
while (!kthread_should_stop()) {
    schedule();
    set_current_state(TASK_INTERRUPTIBLE);
}
__set_current_state(TASK_RUNNING);
return 0;
로그인 후 복사

上面的这些代码属于迁移服务线程 migration_thread,这个线程不断地检查 kthread_should_stop(),直到 kthread_should_stop() 返回 1 它才可以退出循环,也就是说只要 kthread_should_stop() 返回 0 该进程就会一直睡眠。

从代码中我们可以看出,检查 kthread_should_stop() 确实是在进程的状态被置为 TASK_INTERRUPTIBLE 后才开始执行的。因此,如果在条件检查之后但是在 schedule() 之前有其他进程试图唤醒它,那么该进程的唤醒操作不会失效。

요약

위의 논의를 통해 Linux에서 프로세스의 잘못된 깨우기를 방지하는 핵심은 프로세스가 조건을 확인하기 전에 프로세스 상태를 TASK_INTERRUPTIBLETASK_UNINTERRUPTIBLE,并且如果检查的条件满足的话就应该将其状态重新设置为 TASK_RUNNING로 설정하는 것임을 알 수 있습니다.

이렇게 하면 프로세스의 대기 조건이 충족되는지 여부에 관계없이 프로세스가 준비 대기열에서 제거되므로 실수로 절전 상태에 들어가는 일이 없으므로 잘못된 깨우기 문제를 피할 수 있습니다.

위 내용은 Linux 프로세스의 절전 모드 해제 및 절전 모드의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

인기 기사

R.E.P.O. 에너지 결정과 그들이하는 일 (노란색 크리스탈)
3 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 최고의 그래픽 설정
3 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 아무도들을 수없는 경우 오디오를 수정하는 방법
3 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

DeepSeek 웹 버전 입구 DeepSeek 공식 웹 사이트 입구 DeepSeek 웹 버전 입구 DeepSeek 공식 웹 사이트 입구 Feb 19, 2025 pm 04:54 PM

DeepSeek은 웹 버전과 공식 웹 사이트의 두 가지 액세스 방법을 제공하는 강력한 지능형 검색 및 분석 도구입니다. 웹 버전은 편리하고 효율적이며 설치없이 사용할 수 있습니다. 개인이든 회사 사용자이든, DeepSeek를 통해 대규모 데이터를 쉽게 얻고 분석하여 업무 효율성을 향상시키고 의사 결정을 지원하며 혁신을 촉진 할 수 있습니다.

DeepSeek을 설치하는 방법 DeepSeek을 설치하는 방법 Feb 19, 2025 pm 05:48 PM

Docker 컨테이너를 사용하여 사전 컴파일 된 패키지 (Windows 사용자의 경우)를 사용하여 소스 (숙련 된 개발자)를 컴파일하는 것을 포함하여 DeepSeek를 설치하는 방법에는 여러 가지가 있습니다. 공식 문서는 신중하게 문서를 작성하고 불필요한 문제를 피하기 위해 완전히 준비합니다.

Linux 터미널에서 Python 버전을 볼 때 발생하는 권한 문제를 해결하는 방법은 무엇입니까? Linux 터미널에서 Python 버전을 볼 때 발생하는 권한 문제를 해결하는 방법은 무엇입니까? Apr 01, 2025 pm 05:09 PM

Linux 터미널에서 Python 버전을 보려고 할 때 Linux 터미널에서 Python 버전을 볼 때 권한 문제에 대한 솔루션 ... Python을 입력하십시오 ...

Bitget 공식 웹 사이트 설치 (2025 초보자 안내서) Bitget 공식 웹 사이트 설치 (2025 초보자 안내서) Feb 21, 2025 pm 08:42 PM

Bitget은 스팟 거래, 계약 거래 및 파생 상품을 포함한 다양한 거래 서비스를 제공하는 Cryptocurrency 교환입니다. 2018 년에 설립 된이 교환은 싱가포르에 본사를두고 있으며 사용자에게 안전하고 안정적인 거래 플랫폼을 제공하기 위해 노력하고 있습니다. Bitget은 BTC/USDT, ETH/USDT 및 XRP/USDT를 포함한 다양한 거래 쌍을 제공합니다. 또한 Exchange는 보안 및 유동성으로 유명하며 프리미엄 주문 유형, 레버리지 거래 및 24/7 고객 지원과 같은 다양한 기능을 제공합니다.

Gate.io 설치 패키지를 무료로 받으십시오 Gate.io 설치 패키지를 무료로 받으십시오 Feb 21, 2025 pm 08:21 PM

Gate.io는 사용자가 설치 패키지를 다운로드하여 장치에 설치하여 사용할 수있는 인기있는 cryptocurrency 교환입니다. 설치 패키지를 얻는 단계는 다음과 같습니다. Gate.io의 공식 웹 사이트를 방문하고 "다운로드"를 클릭하고 해당 운영 체제 (Windows, Mac 또는 Linux)를 선택하고 컴퓨터에 설치 패키지를 다운로드하십시오. 설치 중에 항 바이러스 소프트웨어 또는 방화벽을 일시적으로 비활성화하여 원활한 설치를 보장하는 것이 좋습니다. 완료 후 사용자는 GATE.IO 계정을 만들려면 사용을 시작해야합니다.

Ouyi OKX 설치 패키지가 직접 포함되어 있습니다 Ouyi OKX 설치 패키지가 직접 포함되어 있습니다 Feb 21, 2025 pm 08:00 PM

세계 최고의 디지털 자산 거래소 인 Ouyi Okx는 이제 안전하고 편리한 거래 경험을 제공하기 위해 공식 설치 패키지를 시작했습니다. OUYI의 OKX 설치 패키지는 브라우저를 통해 액세스 할 필요가 없습니다. 설치 프로세스는 간단하고 이해하기 쉽습니다. 사용자는 최신 버전의 설치 패키지를 다운로드하고 설치를 단계별로 완료하면됩니다.

시스템 재시작 후 UnixSocket의 권한을 자동으로 설정하는 방법은 무엇입니까? 시스템 재시작 후 UnixSocket의 권한을 자동으로 설정하는 방법은 무엇입니까? Mar 31, 2025 pm 11:54 PM

시스템이 다시 시작된 후 UnixSocket의 권한을 자동으로 설정하는 방법. 시스템이 다시 시작될 때마다 UnixSocket의 권한을 수정하려면 다음 명령을 실행해야합니다.

Ouyi Exchange 다운로드 공식 포털 Ouyi Exchange 다운로드 공식 포털 Feb 21, 2025 pm 07:51 PM

OKX라고도하는 Ouyi는 세계 최고의 암호 화폐 거래 플랫폼입니다. 이 기사는 OUYI의 공식 설치 패키지 용 다운로드 포털을 제공하여 사용자가 다른 장치에 OUYI 클라이언트를 설치할 수 있도록합니다. 이 설치 패키지는 Windows, Mac, Android 및 iOS 시스템을 지원합니다. 설치가 완료되면 사용자는 OUYI 계정에 등록하거나 로그인하고 암호 화폐 거래를 시작하며 플랫폼에서 제공하는 기타 서비스를 즐길 수 있습니다.

See all articles