목차
问题描述:
问题追踪
FPM工作流程
简述
详细介绍
php教程 php手册 fpm开启slowlog Fsockopen出现Operation now in progress的

fpm开启slowlog Fsockopen出现Operation now in progress的

Jun 06, 2016 pm 08:12 PM
fpm fsockopen op slowlog 나타나다 켜다

问题描述: 前两天老大跟我讲了一个他们原来遇到的问题,php采用fastcgi的方式启动,并且打开slow log日志,当调用fsockopen读取一个连接,这个连接超过了slowlog设置的时间,fpm进程就会抛出一个warning,用来记录关于这个满请求的一些基本信息。 详细描述

问题描述:

前两天老大跟我讲了一个他们原来遇到的问题,php采用fastcgi的方式启动,并且打开slow log日志,当调用fsockopen读取一个连接,这个连接超过了slowlog设置的时间,fpm进程就会抛出一个warning,用来记录关于这个满请求的一些基本信息。

详细描述如下:

假如我们设置的slowlog 的时间为5s,而通过fsockopen去访问一个不存在的ip和端口,连接超时时间设为10s,代码如下:

图1

我们去访问一个不存在的IP和端口,通过浏览器访问,在错误日志里面我们会收到两个warning,一个是fpm抛出来的slowlog,另外一个是PHP Warning:? fsockopen(): unable to connect to 2.3.2.1:9999 (Operation now in progress)。

正常情况来讲,fsockopen连接出错应该出现Connection timed out,但事实并非如此,似乎fpm抛出脚本超时之后就结束了,为什么?

后来在命令行下运行该脚本,却没有出现Operation now in progress,是fsockopen Connection timed out的错误,这就说明并非是fsockopen的问题,发生在fpm上。

本次问题追踪分为两个部分,本文主要介绍fpm的运行机制,关于答案请看

fpm开启slowlog Fsockopen出现Operation now in progress的问题追踪二

问题追踪

因为是在线上出现的问题,线上php的版本是5.2.8,我本地装的是php 5.3,经过测试,php 5.3也有同样的问题。

Operation now in progress 这个异常,本身是没有任何问题的,它是非阻塞connect的一个返回值,该值表明connect正在进行中,等等,非阻塞?可能问题就出现在这里,

如果使用非阻塞connect,后面应该通过调用select,检查select的写事件,一旦返回,则说明有可用数据接收。

要定位这个问题,似乎没有别的办法,只能去看fpm的源码了,在翻看源码时也确实定位到了问题根源。

不过要弄清这个问题,我们先要明白fpm的工作流程。

FPM工作流程

简述

Fpm是多进程的程序,fpm启动时它通过一个master,fork出 max_children为工作进程,并把子进程的进程id及其他相关信息保存到 struct fpm_worker_pool_s指向的children指针中。

工作进程用来接收网络请求,当有链接通过nginx问时,nginx发现我们访问的是php文件,它就会把该文件的绝对目录通过fastcgi_pass指定的网络端口传递到fpm的9000端口,

fpm接收到该请求,并从children中查找空闲进程,通过该空闲进程去处理请求。

详细介绍

图2

在翻看fpm源码过程当中,发现主进程监听的不是网络事件,而是时间事件,现在的时间超过事件所设定的时间后,则会触发fpm_got_signal函数,该函数通过管道sp[2]来进行主进程和子进程的通信,它主要用来处理SIGCHLD、SIGINT、SIGTERM、SIGQUIT、SIGUSR1、SIGUSR2这几个信号,不同的信号有不同的处理逻辑:

代码段1:

static void fpm_got_signal(struct fpm_event_s *ev, short which, void *arg) /* {{{ */
{
    char c;
    int res, ret;
    //fd是sp[2]管道
    int fd = ev->fd;
    ........
switch (c) {
            case 'C' :                  /* SIGCHLD */
                zlog(ZLOG_DEBUG, "received SIGCHLD");
                //调用waitpid,等待子进程产生SIGCHLD
                fpm_children_bury();
                break;
            case 'I' :                  /* SIGINT  */
                zlog(ZLOG_DEBUG, "received SIGINT");
                zlog(ZLOG_NOTICE, "Terminating ...");
                fpm_pctl(FPM_PCTL_STATE_TERMINATING, FPM_PCTL_ACTION_SET);
                break;
            case 'T' :                  /* SIGTERM */
                zlog(ZLOG_DEBUG, "received SIGTERM");
                zlog(ZLOG_NOTICE, "Terminating ...");
                fpm_pctl(FPM_PCTL_STATE_TERMINATING, FPM_PCTL_ACTION_SET);
                break;
            case 'Q' :                  /* SIGQUIT */
                zlog(ZLOG_DEBUG, "received SIGQUIT");
                zlog(ZLOG_NOTICE, "Finishing ...");
                fpm_pctl(FPM_PCTL_STATE_FINISHING, FPM_PCTL_ACTION_SET);
                break;
    ........
}
로그인 후 복사

下面来看一个无比复杂的图:

图3

为了搞清楚细节,阅读了大部分fpm源码,画出了上面的图,很复杂,

看不懂没关系,我根据源码来慢慢讲

Fpm的main函数在sapi/fpm/fpm/fpm_main.c 1548行,

上面一部分都可以忽略,用来处理fpm启动参数和php环境的初始化,来看1824行,

代码段2:

int main(int argc,char **argv){
.........
 //fpm初始化
    if (0 > fpm_init(argc, argv, fpm_config ? fpm_config : CGIG(fpm_config), fpm_prefix, fpm_pid, test_conf, php_allow_to_run_as_root, force_daemon)) {
        //出错-----
        if (fpm_globals.send_config_pipe[1]) {
            int writeval = 0;
            zlog(ZLOG_DEBUG, "Sending \"0\" (error) to parent via fd=%d", fpm_globals.send_config_pipe[1]);
            write(fpm_globals.send_config_pipe[1], &writeval, sizeof(writeval));
            close(fpm_globals.send_config_pipe[1]);
        }
        return FPM_EXIT_CONFIG;
    }
.........
}
로그인 후 복사

Fpm_init进行了初始化,也就是图中A的位置,它的主要工作正如图3所标示,下面是主要代码

代码段3:

int fpm_init(int argc, char **argv, char *config, char *prefix, char *pid, int test_conf, int run_as_root, int force_daemon) /* {{{ */
{
..........
 if (0 > fpm_php_init_main()           ||
        0 > fpm_stdio_init_main()         ||//初始化io
        0 > fpm_conf_init_main(test_conf, force_daemon) ||//加载fpm 配置文件
        0 > fpm_unix_init_main()          ||
        0 > fpm_scoreboard_init_main()    ||
        0 > fpm_pctl_init_main()          ||
        0 > fpm_env_init_main()           ||
        0 > fpm_signals_init_main()       ||//注册进程信号的callback,很关键
        0 > fpm_children_init_main()      ||
        0 > fpm_sockets_init_main()       ||//socket 初始化
        0 > fpm_worker_pool_init_main()   ||//工作池初始化
        0 > fpm_event_init_main()) {//事件IO初始化
        if (fpm_globals.test_successful) {
            exit(FPM_EXIT_OK);
        } else {
            zlog(ZLOG_ERROR, "FPM initialization failed");
            return -1;
        }
    }
    if (0 > fpm_conf_write_pid()) {//写入fpm 的进程id
        zlog(ZLOG_ERROR, "FPM initialization failed");
        return -1;
    }
..........
}
로그인 후 복사

主要工作已经注释到源码里,这里不细谈,

紧接着在 main函数中 有一个fpm_run函数

代码段4:

.......
//fcgi_fd 是socket句柄
    fcgi_fd = fpm_run(&max_requests);
    parent = 0;
    //子进程继续往下执行,父进程会在fpm_run中while
    /* onced forked tell zlog to also send messages through sapi_cgi_log_fastcgi() */
    zlog_set_external_logger(sapi_cgi_log_fastcgi);
........
로그인 후 복사

图3里下面部分操作都的封装到这个函数里了

代码段5:

int fpm_run(int *max_requests) /* {{{ */
{
    struct fpm_worker_pool_s *wp;
    /* create initial children in all pools */
    for (wp = fpm_worker_all_pools; wp; wp = wp->next) {
        int is_parent;
        is_parent = fpm_children_create_initial(wp);
        //子进程
        if (!is_parent) {
            goto run_child;
        }
        /* handle error */
        if (is_parent == 2) {//子进程创建失败
            fpm_pctl(FPM_PCTL_STATE_TERMINATING, FPM_PCTL_ACTION_SET);
            fpm_event_loop(1);
        }
    }
    /* run event loop forever */
    //主进程监听事件
    fpm_event_loop(0);
run_child: /* only workers reach this point */
    fpm_cleanups_run(FPM_CLEANUP_CHILD);
    *max_requests = fpm_globals.max_requests;
    ///返回socket句柄
    return fpm_globals.listening_socket;
}
로그인 후 복사

该函数先创建子进程,把进程相关信息放在struct fpm_worker_pool_s *wp这个指针里,
父进程调用fpm_event_loop(0),子进程直接返回sock句柄,然后继续运行 fpm_main.c 1848之后的代码,进行accept操作;

fpm_event_loop是时间事件监听操作,

代码段6:

void fpm_event_loop(int err) /* {{{ */
{
  static struct fpm_event_s signal_fd_event;
    /* sanity check */
    if (fpm_globals.parent_pid != getpid()) {
        return;
    }
    //注册callback = fpm_got_signal
    /**
        设置signal_fd_event参数,ev->fd=sp[0]
        fpm_signals_get_fd()是管道句柄sp[0]:读;
    **/
    fpm_event_set(&signal_fd_event, fpm_signals_get_fd(), FPM_EV_READ, &fpm_got_signal, NULL);
    fpm_event_add(&signal_fd_event, 0);
    /* add timers */
    if (fpm_globals.heartbeat > 0) {
        //fpm超时检测处理
        fpm_pctl_heartbeat(NULL, 0, NULL);
    }
    .......
  while(1){
  ...............
 //wait事件
        ret = module->wait(fpm_event_queue_fd, timeout);
.............
          while (q) {
            fpm_clock_get(&now);
            if (q->ev) {
                if (timercmp(&now, &q->ev->timeout, >) || timercmp(&now, &q->ev->timeout, ==)) {
                    //处理信号SIGCHILD  fpm_got_signal
                    fpm_event_fire(q->ev);
.............
          }
      }
   }
}
로그인 후 복사

注册fpm_got_signal回调函数,该函数会在下面的监听时间事件时执行。
注意看fpm_pctl_heartbeat函数,这里就是执行慢脚本记录的地方,跟进去看看,
fpm_process_ctl.c 442行

代码段7:

void fpm_pctl_heartbeat(struct fpm_event_s *ev, short which, void *arg) /* {{{ */
{
    static struct fpm_event_s heartbeat;
    struct timeval now;
    if (fpm_globals.parent_pid != getpid()) {
        return; /* sanity check */
    }
    if (which == FPM_EV_TIMEOUT) {
        fpm_clock_get(&now);//获取时间
        //检测slowlog,
        fpm_pctl_check_request_timeout(&now);
        return;
    }
    /* ensure heartbeat is not lower than FPM_PCTL_MIN_HEARTBEAT */
    fpm_globals.heartbeat = MAX(fpm_globals.heartbeat, FPM_PCTL_MIN_HEARTBEAT);
    /* first call without setting to initialize the timer */
    zlog(ZLOG_DEBUG, "heartbeat have been set up with a timeout of %dms", fpm_globals.heartbeat);
    fpm_event_set_timer(&heartbeat, FPM_EV_PERSIST, &fpm_pctl_heartbeat, NULL);
    fpm_event_add(&heartbeat, fpm_globals.heartbeat);
}
로그인 후 복사

调用了fpm_ptcl_check_request_timeout函数,可能会发现只有witch== FPM_EV_TIMEOUT的时候,才会调用的,上面的函数传的witch是0 ,它应该是执行不了的,是的,第一次是不会执行的,首次执行会调用463和464行,用来注册时间事件,把fpm_ptcl_hearbeat作为一个回调函数来使用的,所以这里并不影响我们,继续查看fpm_pctl_check_request_timeout函数

代码段8:

static void fpm_pctl_check_request_timeout(struct timeval *now) /* {{{ */
{
    ........
                //检测slow log
                fpm_request_check_timed_out(child, now, terminate_timeout, slowlog_timeout);
       ..........
}
로그인 후 복사

又是一个调用,fpm_request_check_timed_out,继续跟
fpm_request.c 230行,终于到了,

代码段9:

void fpm_request_check_timed_out(struct fpm_child_s *child, struct timeval *now, int terminate_timeout, int slowlog_timeout) /* {{{ */
{
.........
#if HAVE_FPM_TRACE
        /**
            检测子进程运行状态和时间
        **/
        if (child->slow_logged.tv_sec == 0 && slowlog_timeout &&
                proc.request_stage == FPM_REQUEST_EXECUTING && tv.tv_sec >= slowlog_timeout) {
            str_purify_filename(purified_script_filename, proc.script_filename, sizeof(proc.script_filename));
            child->slow_logged = proc.accepted;
            child->tracer = fpm_php_trace;//注册输出trace信息的callback函数
            //暂停子进程
            fpm_trace_signal(child->pid);
            //记录slow log的日志
            zlog(ZLOG_WARNING, "[pool %s] child %d, script '%s' (request: \"%s %s\") executing too slow (%d.%06d sec), logging",
                child->wp->config->name, (int) child->pid, purified_script_filename, proc.request_method, proc.request_uri,
                (int) tv.tv_sec, (int) tv.tv_usec);
        }
        else
#endif
        if (terminate_timeout && tv.tv_sec >= terminate_timeout) {
            str_purify_filename(purified_script_filename, proc.script_filename, sizeof(proc.script_filename));
            fpm_pctl_kill(child->pid, FPM_PCTL_TERM);
            zlog(ZLOG_WARNING, "[pool %s] child %d, script '%s' (request: \"%s %s\") execution timed out (%d.%06d sec), terminating",
                child->wp->config->name, (int) child->pid, purified_script_filename, proc.request_method, proc.request_uri,
                (int) tv.tv_sec, (int) tv.tv_usec);
        }
    }
.........
}
로그인 후 복사

这里是关键代码,上面的那个判断是,如果开启了慢日志 && slowlog_timeout&& 当前进程的状态为Running && 进程执行的时间大于我们配置的时间,
slowlog_timeout是php-fpm.conf中配置的request_slowlog_timeout参数,
然后会注册一个callback函数fpm_php_trace,用来在主进程中执行,暂停子进程,最后记录slowlog的日志。

if (terminate_timeout && tv.tv_sec >= terminate_timeout) { 这里开始是中断请求的代码,如果设置了request_terminate_timeout,这里就会被执行。
那上面那个暂停进程是什么意思?为什么要暂停子进程?
暂停子进程的目的,是希望能让父进程获取子进程当前运行时的详细信息,用来打印trace,
现在回到fpm_event_loop函数,来看看这个过程,回到 fpm_event_loop函数

图4

410行是epoll_wait事件,它支持select、poll、epoll
看428行,fpm_event_fire函数,将要执行fpm_got_signal函数,还记得上面说过的一个用来回调的信号处理函数吗?

图5

对就是这里,它将会在产生时间事件的时候被执行:
fpm_events.c 52行
图6

fpm_children_bury函数里调用waitpid,

图7

WNOHANG|WUNTRACED的意思是有任何进程被暂停则立即返回,
如果检测到进程被暂停,则会执行fpm_php_trace抛出trace信息到日志中,(fpm_php_trace是上面代码段9注册的callback),最后发送继续运行的信号给子进程。

图8

子进程收到继续运行的信号会,会继续运行fpm_main.c 1848之后的代码,接收用户请求,处理php脚本。

Fpm的执行流程就是这样,很复杂,涉及的代码量很多,需要慢慢看。

Fpm的工作流程大概是明白了,但是上面的问题还没有找到答案,为什么抛出慢脚本的日志后进程就挂了?

这个问题的答案请参看:fpm开启slowlog Fsockopen出现Operation now in progress的问题追踪二

原文出处:http://www.imsiren.com/archives/1088
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 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 옷 제거제

Video Face Swap

Video Face Swap

완전히 무료인 AI 얼굴 교환 도구를 사용하여 모든 비디오의 얼굴을 쉽게 바꾸세요!

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

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

SublimeText3 중국어 버전

SublimeText3 중국어 버전

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

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

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

Win11에서 메모리 무결성을 켜야 합니까? Win11에서 메모리 무결성을 켜야 합니까? Jan 06, 2024 am 08:53 AM

win10과 마찬가지로 win11도 시스템을 보호하기 위해 메모리 무결성 기능을 도입했지만 많은 친구들은 이 기능이 어떤 용도로 사용되는지 모릅니다. 그렇다면 win11 메모리 무결성을 켜야 하는 걸까요? 사실 이것이 컴퓨터와 관련이 있는 걸까요? 체계. win11에서 메모리 무결성을 켜야 하는지: 대답: 컴퓨터 구성이 높거나 일상적인 사무실 오디오 및 비디오용인 경우 컴퓨터 구성이 좋지 않거나 고성능을 추구하는 경우에는 켤 수 있습니다. 켜서는 안 됩니다. win11 메모리 무결성 소개: 1. 메모리 무결성의 원칙은 하드웨어 가상화가 격리된 환경을 생성한다는 것입니다. 2. 시스템 및 메모리 보안을 보호합니다. 3. 단점은 이 기능을 켜면 언제든지 실행되어 메모리를 차지하고 성능이 저하된다는 점입니다. 4. 그리고 일단 켜지면 끄는 것이 더 번거로울 것입니다.

DLSS를 활성화하는 방법은 무엇입니까? DLSS 오픈 전략 DLSS를 활성화하는 방법은 무엇입니까? DLSS 오픈 전략 Mar 13, 2024 pm 07:34 PM

NVIDIA에는 dlss 기능이 있습니다. 사용자가 dlss를 켜면 게임 프레임 속도가 크게 향상될 수 있습니다. 따라서 많은 친구들이 편집자에게 dlss를 켜는 방법을 문의합니다. 먼저 그래픽 카드가 dlss를 지원하고 게임이 dlss를 지원하는지 확인한 다음 게임에서 활성화할 수 있습니다. 아래의 구체적인 튜토리얼을 살펴보겠습니다. 답변: DLSS는 일반적으로 게임에서 열어야 합니다. DLSS를 활성화하려면 기기 및 게임의 조건을 충족해야 합니다. dlss는 "레이 트레이싱 효과"이므로 게임 설정에 들어갈 수 있습니다. 그런 다음 "이미지 또는 그래픽" 설정으로 이동합니다. 그런 다음 "Ray Tracing Lighting"을 찾아 클릭하여 엽니다. 디

Win11에서 VBS 기능을 활성화하는 방법 Win11에서 VBS 기능을 활성화하는 방법 Dec 25, 2023 pm 02:09 PM

이전에 VBS를 닫은 후 열 수도 있습니다. VBS를 여는 방법을 살펴보겠습니다. 실제로는 매우 간단합니다. win11vbs를 여는 방법: 1. 먼저 "시작 메뉴"를 클릭합니다. 2. 그런 다음 "Windows 터미널"을 클릭합니다. 3. 그런 다음 "bcdedit/sethypervisorlaunchtypeauto"를 입력합니다. 4. 그런 다음 컴퓨터를 다시 시작하고 시작 메뉴를 열고 검색 창에서 "시스템 정보"를 검색하십시오. 5. 그런 다음 "가상화 기반 보안"이 켜져 있는지 확인하십시오.

GPU 하드웨어 가속을 활성화해야 합니까? GPU 하드웨어 가속을 활성화해야 합니까? Feb 26, 2024 pm 08:45 PM

하드웨어 가속 GPU를 활성화해야 합니까? 지속적인 기술의 발전과 진보에 따라 컴퓨터 그래픽 처리의 핵심 구성요소인 GPU(Graphics Processor Unit)는 중요한 역할을 하고 있습니다. 그러나 일부 사용자는 하드웨어 가속을 켜야 하는지 여부에 대해 질문할 수 있습니다. 이 기사에서는 GPU에 대한 하드웨어 가속의 필요성과 하드웨어 가속을 켤 때 컴퓨터 성능과 사용자 경험에 미치는 영향에 대해 설명합니다. 먼저, 하드웨어 가속 GPU가 어떻게 작동하는지 이해해야 합니다. GPU는 특화된

win10에서 이더넷 비활성화를 활성화하는 방법: 세부 단계 win10에서 이더넷 비활성화를 활성화하는 방법: 세부 단계 Jan 03, 2024 pm 09:51 PM

win10 시스템을 사용하는 친구들은 이더넷 비활성화를 활성화하는 방법을 자주 묻습니다. 실제로 이 작업은 수행하기 전에 네트워크 설정에 들어가야 합니다. 다음으로 살펴보겠습니다. win10에서 이더넷을 비활성화하는 방법: 1. 먼저 오른쪽 하단에 있는 네트워크 연결 아이콘을 클릭하여 네트워크 및 인터넷 설정을 엽니다. 2. 그런 다음 이더넷을 클릭하십시오. 3. 그런 다음 "어댑터 옵션 변경"을 클릭하십시오. 4. 이 시점에서 "이더넷"을 마우스 오른쪽 버튼으로 클릭하고 비활성화를 선택할 수 있습니다.

Windows 10에서 마이크 권한을 활성화하는 방법 Windows 10에서 마이크 권한을 활성화하는 방법 Jan 02, 2024 pm 11:17 PM

최근에 내 친구가 컴퓨터 마이크를 켤 수 없다는 사실을 발견했습니다. 요즘에는 데스크톱 컴퓨터와 노트북 모두 마이크 기능이 탑재되어 있어 매우 편리하지만 사용 중에 갑자기 마이크 문제가 발생하는 경우가 많습니다. 내 컴퓨터 마이크에서 소리가 나지 않습니다. 아래 편집자가 컴퓨터 마이크를 켜서 문제를 해결하는 방법을 알려줄 것입니다. 자세한 내용을 함께 살펴보겠습니다. Windows 10에서 마이크 권한을 활성화하는 방법: 1. Windows 10 시스템에서 녹음기를 켜면 "설정에서 마이크를 설정해야 합니다"라는 메시지가 나타납니다. 2. 이때 화면 왼쪽 하단에 있는 시작 버튼을 클릭하고 팝업 메뉴에서 "설정" 메뉴 항목을 선택할 수 있습니다. 3. 열리는 Windows 설정 창에서 "개인정보" 아이콘을 클릭하세요. 4

Amap에서 실시간 교통 상황을 활성화하는 방법 Amap에서 실시간 교통 상황을 활성화하는 방법 Feb 28, 2024 pm 07:22 PM

AMAP 지도 소프트웨어는 뛰어난 기능으로 사용자의 여행에 큰 편의를 제공합니다. 그 중 실시간 교통 기능은 사용자가 도로 상황을 보다 정확하게 파악하고 혼잡을 피하며 최적의 경로를 선택할 수 있도록 도와준다는 점에서 사용자들의 높은 평가를 받고 있다. 그런 다음 Zian은 Amap 지도의 실시간 교통 상황을 열 수 있습니다. 이에 대해 더 알고 싶은 사용자는 아래 편집자의 튜토리얼 가이드를 따라 더 자세히 알아볼 수 있습니다! Amap 지도에서 실시간 교통 상황을 켜는 방법 답변: [Amap] - [레이어] - [교통 상황]. 구체적인 단계: 1. 먼저 Amap 소프트웨어를 열고 홈페이지에 들어갑니다. 오른쪽 상단에 알림, 레이어, 피드백 버튼이 있습니다. 2. 클릭하면 대화 상자가 나타납니다. . 여기에서 [교통 상황]을 클릭합니다.

Win11에서 절전 모드를 활성화하는 방법 Win11에서 절전 모드를 활성화하는 방법 Jan 08, 2024 pm 02:45 PM

오랫동안 컴퓨터를 종료하고 싶지만 종료하고 싶지 않은 경우 컴퓨터를 절전 모드로 전환할 수 있습니다. 그러나 win11을 업데이트한 후에는 win11 절전 모드를 켜는 방법을 찾을 수 없습니다. 사실 제어판에서만 켜면 됩니다. win11에서 최대 절전 모드를 활성화하는 방법 방법 1: 시작 메뉴를 사용하여 하단 시작 메뉴를 클릭한 다음 전원 버튼을 클릭하여 최대 절전 모드로 전환합니다. 방법 2: 고급 사용자 메뉴 사용 1. 바탕 화면의 검색 상자에서 "제어판"을 검색하여 열고 "하드웨어 및 소리" 옵션을 클릭한 후 전원 옵션에서 "전원 버튼의 기능 변경"을 클릭합니다. 2. 입력 후 "현재 사용할 수 없는 설정 변경"을 클릭하고, 마지막으로 "최대 절전 모드"를 체크한 후 저장하여 최대 절전 모드 기능을 실행합니다. 방법 3: 지침

See all articles