linux学习(等待+进程替换初识)[9]

阻塞等待

一般在内核中阻塞(伴随着被切换),等待被唤醒(放在等待队列【一种数据结构】中)
在Linux中,阻塞等待是指一个进程或线程被暂停执行,直到某个条件满足或事件发生。下面介绍两种常见的阻塞等待方式:

  1. 阻塞等待系统调用:在Linux中,许多系统调用函数可以使进程或线程进入阻塞等待状态,直到某个条件满足。例如,常见的阻塞等待系统调用包括:

    • read():从文件描述符中读取数据,如果没有数据可读,则进程会阻塞等待,直到有数据可读或出现错误。
    • write():向文件描述符中写入数据,如果写入的缓冲区已满,则进程会阻塞等待,直到有空间可写或出现错误。
    • sleep():使进程休眠指定的时间,进程会阻塞等待,直到休眠时间结束。
    • wait():等待子进程结束,进程会阻塞等待,直到子进程结束或出现错误。

    当条件满足时,阻塞等待的系统调用会返回,并使进程或线程继续执行。

  2. 阻塞等待同步原语:除了系统调用外,Linux还提供了一些同步原语,用于实现线程之间的阻塞等待。这些同步原语包括:

    • 互斥锁(Mutex):线程可以使用互斥锁来保护共享资源,当一个线程持有互斥锁时,其他线程尝试获取锁会被阻塞等待,直到锁被释放。
    • 条件变量(Condition Variable):线程可以使用条件变量来等待某个条件满足,当条件不满足时,线程会阻塞等待在条件变量上,直到其他线程发出条件满足的信号。
    • 信号量(Semaphore):线程可以使用信号量来控制对共享资源的访问,当信号量的值为0时,线程会阻塞等待,直到信号量的值大于0。

    这些同步原语可以帮助线程进行有效的互斥和同步,并实现线程之间的阻塞等待。

非阻塞等待

非阻塞等待是指进程或线程在等待某个条件满足时,不会被暂停执行,而是继续执行其他任务。在Linux中,非阻塞等待通常使用以下两种方式实现:

  1. 轮询:进程或线程可以通过轮询的方式来检查条件是否满足。它会反复地检查条件,如果条件满足,则继续执行相应的操作;如果条件不满足,则继续轮询或执行其他任务。轮询可以使用循环结构实现,例如使用while循环。

    以下是一个简单的示例,展示了如何使用轮询实现非阻塞等待:

    while (!condition) {
        // 执行其他任务
    }
    // 条件满足,执行相应的操作
    

    轮询的优点是简单直接,但它可能会消耗大量的CPU资源,并且可能导致延迟。

  2. 异步事件处理:进程或线程可以将等待任务交给操作系统或其他模块处理,并在条件满足时通过回调函数或事件通知方式得到通知。这样,进程或线程可以继续执行其他任务,而不需要主动轮询。

    异步事件处理通常涉及使用特定的API或框架,例如Linux中的epollselectpoll等系统调用,或者使用异步编程框架,例如libevent、Boost.Asio等。

    以下是一个简单的示例,展示了如何使用异步事件处理实现非阻塞等待:

    // 创建事件循环
    event_loop = create_event_loop();
    
    // 注册事件处理函数
    register_event_handler(event_loop, event_type, event_handler);
    
    // 启动事件循环
    run_event_loop(event_loop);
    

    当事件发生时,事件处理函数 event_handler 将被调用,进程或线程可以在事件处理函数中执行相应的操作。

    异步事件处理的优点是可以提高系统的性能和响应性,但它通常需要更复杂的编程模型和代码结构。

非阻塞等待在处理异步任务和事件驱动编程中非常常见,它可以提高系统的并发性和吞吐量。具体使用哪种非阻塞等待方式取决于您的需求和场景。如果您有特定的问题或需求,请提供更多详细信息,我将尽力提供帮助。
在这里插入图片描述
在这里插入图片描述

进程替换

替换原理

内核结构没有变,并没有创建新的进程
在这里插入图片描述
在这里插入图片描述
如何理解将程序放入内存当中:加载!exec*系列函数
在这里插入图片描述
可变参数列表最后一个参数必须是NIULL,标识参数传递完毕!
在这里插入图片描述

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>

int main()
{
    extern char **environ;
    pid_t id = fork();
    if(id == 0)
    {
        //child
        printf("我是子进程: %d\n", getpid());
        //execl: 如果替换成功,不会有返回值,如果替换失败,一定有返回值 ==》如果失败了,必定返回 ==》 只要有返回值,就失败了
        //不用对该函数进行返回值判断,只要继续向后运行一定是失败的!
        //execl("/bin/ls", "ls", "-a", "-ln", NULL); //lsssss: 不存在
        //char *const myargv[] = {
        //    "ls",
        //    "-a",
        //    "-l",
        //    "-n",
        //    NULL
        //};
        //execv("/bin/ls", myargv); //lsssss: 不存在
        //execlp("ls", "ls", "-a", "-l", "-n", NULL);
        //execvp("ls", myargv);
        //char *const myenv[] = {
        //    "MYENV=YouCanSeeMe",
        //    NULL
        //};
        //putenv("MYENV=YouCanSeeMe");
        //execle("./exec/otherproc", "otherproc", NULL, environ);
        //execl("./exec/shell.sh", "shell.sh", NULL);
        execl("./exec/test.py", "test.py", NULL);
        exit(1);
    }

    sleep(1);
    //father
    int status = 0;
    printf("我是父进程: %d\n", getpid());
    waitpid(id, &status, 0);
    printf("child exit code: %d\n", WEXITSTATUS(status));

    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值