Linux编程:1. 协程的设计原理

一、进程

进程是指正在运行的程序实例,在操作系统中,每个进程都有自己的内存空间、执行状态和资源使用情况等属性。一个进程可以包含多个线程,它们共享该进程的内存空间和其他资源。操作系统通过进程管理来控制各个进程之间的资源分配,保证它们能够合理地协同工作和互不干扰。

二、线程

线程是操作系统能够进行运算调度的最小单位。它由线程ID、程序计数器、寄存器集合和堆栈组成。线程共享进程中的数据,但每个线程都拥有自己的寄存器和栈空间,因此可以独立运行,并且在被抢占后能够恢复执行状态。一个进程至少有一个线程,如果一个进程只有一个线程,则称为单线程应用程序,而拥有多个线程的进程称为多线程应用程序

三、协程

1. 什么是协程

协程(Coroutine)是一种用户态的轻量级线程,也称为微线程。协程不同于操作系统提供的线程,它在程序中是由用户自己控制调度的,可以看做是一种特殊的函数或代码块,可以暂停执行并保存当前状态,在需要的时候恢复执行。协程通常用于异步编程、高并发、网络编程等领域,能够有效地提高程序的性能和资源利用率

2. 为什么要有协程

协程可以将一个程序分成多个独立的任务,每个任务都可以被暂停和恢复执行,并且在执行的过程中可以与其他任务交替执行。这样可以避免线程切换和上下文切换带来的性能损失,提高程序的并发处理能力和效率。

协程还可以用于实现异步编程,通过将IO等耗时操作转化为协程的挂起操作,可以减少线程数量和内存占用,提高程序的可维护性和扩展性。

另外,协程还可以简化编写异步代码的复杂性,让程序员更加专注于业务逻辑的实现,提高开发效率。

3. 进程、线程、协程有什么区别

  1. 进程是操作系统分配资源的基本单位,每个进程拥有独立的内存空间、文件句柄和系统资源,进程之间无法直接共享数据和资源。进程启动需要一定的时间和空间开销。
  2. 线程是程序执行的最小单位,一个进程可以包含多个线程。线程共享进程的地址空间和系统资源,线程之间的通信比进程间通信更加高效。
  3. 协程也称为微线程或用户级线程,是一种由程序员控制的轻量级线程。与线程不同,协程没有操作系统调度的开销,其切换只需在应用程序内部完成。协程通常使用yield函数或者await关键字来主动让出CPU执行权,并保存当前状态以便稍后恢复。

4. 协程的原语操作

  1. 创建协程:创建一个新的协程并分配给指定的函数。
  2. 启动协程:启动一个已创建的协程并开始执行其中的代码。
  3. 暂停协程:将当前正在执行的协程暂停,并保存其状态以便稍后继续执行。
  4. 恢复协程:从上一次中断的位置恢复执行协程,并且传递相应的参数。
  5. 结束协程:结束当前正在执行的协程,并返回相应的值。
  6. 同步通信:实现两个协程之间的同步通信,例如发送和接收消息或共享变量。
  7. 异步通信:实现两个协程之间的异步通信,例如通过消息队列进行通信。
  8. 互斥锁:保护共享资源以防止多个协程同时访问该资源。
  9. 条件变量:在协程之间等待和通知事件发生的机制。
  10. 定时器:设置计时器以触发协程中的事件。

5. 协程的切换

协程的切换是指在协程执行过程中,将当前协程的执行状态暂停,并切换到另一个协程继续执行。这种切换一般通过特殊的语法来实现,例如Python中的yield、asyncio库中的await等。

当一个协程调用了yield或者await时,它就会自动释放控制权,让出CPU资源给其他协程执行。同时,当前协程的执行状态会被保存下来,以便下次恢复执行。当其他协程执行完成后,控制权又会返回到原来的协程,继续执行之前的任务。

协程的切换是非常快速的,因为它并不需要像线程切换那样涉及到系统调用和上下文切换。而且由于协程的轻量级特性,可以在同一个线程内创建大量的协程,以充分利用CPU资源并提高程序的并发处理能力。

6. 协程的struct如何定义

typedef struct coroutine_s {
    void (*func)(struct coroutine_s *); // 协程函数指针
    void *arg;         // 协程执行函数参数指针
    char *stack;       // 协程栈空间指针
    size_t stack_size; // 协程栈空间大小
    jmp_buf env;   // 协程上下文
    int status; // 协程状态 0: ready, 1: running, -1: finished
} coroutine_t;

7. 协程的schedule如何定义

typedef struct coroutine_s {
    void (*func)(struct coroutine_s *); // 协程函数指针
    void *arg;         // 协程执行函数参数指针
    char *stack;       // 协程栈空间指针
    size_t stack_size; // 协程栈空间大小
    jmp_buf env;   // 协程上下文
    int status; // 协程状态 0: ready, 1: running, -1: finished
} coroutine_t;

struct schedule {
    char stack[1024*1024];         // 协程池(每个协程分配的栈大小为1MB)
    ucontext_t main;               // 主函数上下文
    int running_coroutine;         // 当前运行的协程ID
    coroutine_t **coroutines; // 协程数组指针
    int max_index;                 // 最大协程数
    int cur_index;                 // 当前协程数
};

8. 协程调度策略如何实现

  1. 非抢占式调度:当一个协程执行完毕或者主动让出 CPU 时,才会选择下一个可运行的协程执行。这种方式适用于任务比较简单、轻量级的场景。
  2. 抢占式调度:当一个协程运行时间超过一定阈值或者发生 IO 等阻塞操作时,会被强制挂起,让其他协程运行。这种方式适用于任务比较复杂、需要长时间运行的场景。
  3. 协作式调度:协程之间必须显式地协调来进行切换,即只有在某个协程主动让出 CPU 的时候,才会进行下一个协程的调度。这种方式适用于需要更加精细控制的场景,例如游戏引擎中的帧率控制。
  4. 多级反馈队列调度:将所有协程分为几个优先级队列,每个队列的优先级不同。新的协程始终进入最高优先级队列,如果一个协程运行时间超过一定时间,则被移到一个低优先级队列。这种方式适用于需要平衡任务执行效率和公平性的场景。
  5. 时间片轮转调度:将 CPU 时间分成若干个时间片,每个协程运行一段时间后,强制切换到下一个协程。这种方式适用于需要在多个协程之间均匀分配 CPU 时间的场景。

推荐一个零声学院免费公开课程,个人觉得老师讲得不错,分享给大家:

Linux,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK等技术内容,立即学习

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Linux C编程经典》是一本经典的Linux C编程指南,是程序员学习Linux下C语言编程的重要参考书籍。 这本书主要包含了Linux操作系统下C语言编程的基本知识、高级技巧和实践经验。首先,它详细介绍了Linux环境的特点和基本概念,包括进程、线程、文件系统等。同时,还介绍了Linux系统编程的基本工具,例如gcc编译器和make工具,帮助读者正确地配置和调试开发环境。 接下来,书中深入讲解了C语言的基本语法和常用库函数,在此基础上展开了各种实例和代码片段。这些实例涵盖了Linux下常见的编程任务和问题,如多线程处理、网络编程、进程间通信等。通过这些实例,读者可以逐步掌握Linux C编程的核心技术和解决实际问题的方法。 此外,书中还介绍了一些高级的Linux C编程技巧和优化策略。比如,如何利用系统调用和库函数进行文件和网络操作,如何使用共享内存和信号量进行进程间同步,以及如何进行性能调优和debugging等。这些知识点对于提升编程效率和代码质量非常有帮助。 总的来说,《Linux C编程经典》是一本理论与实践相结合的优秀书籍。它不仅系统地介绍了Linux C编程的基础知识,还提供了大量实用的示例和技巧。无论是初学者还是有一定经验的程序员,阅读并掌握这本书都将对他们深入理解Linux C编程有很大帮助。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值