linux系统调用yield和pause进程让出cpu

道生一,一生二,二生三,三生万物。

linux进程

每个进程对应一个 task_struct 数据结构,这个数据结构包含了进程的所有的信息,这个结构非常复杂,参考linux内核结构体说明_晓镁的博客-CSDN博客

linux操作系统不会区分线程和进程,线程也是通过进程来实现的。进程是资源管理的最小单元,线程是程序执行的最小单元。

进程有独立的资源,进程fork出来的子进程继承父进程资源。fork()后父子进程拥有相同内容的代码段、数据段和用户堆栈,实际上是父进程克隆复制了自己的PCB块。

子进程从父进程继承的资源有:用户/组号、进程组号、env,堆栈、共享内存、当前/根目录、打开的文件描述符、信号等。

子进程独有进程号、文件描述符、不继承异步输入和输出、不继承进程正文数据和memory locks。

这里感兴趣的话可以继续研究一下,fork()和vfork()父子进程执行顺序问题,及其他区别。

0 号进程是无中生有出来的,是所有进程的祖先,是为道。

1号init进程是内核启动的用户级进程,引导进程,init是第一个进程,是为一。

 2号kthreadd进程是内核线程的父进程or祖先进程,是为二。

在编写内核驱动代码的时候,会经常用到kthread_create函数,其核心是使用kthread_create_list全局链维护kthread。常见的pthread_create、pthread_join、pthread_exit为用户态线程函数。

所以进程都是通过其他进程创建出来的,整进程组织架构看起来是一个树。

进程调度

yield系统调用

yield、pause让出cpu。

运行在用户态的进程,想实现一些更底层的操作,可以通过syscall进入到内核态。

yield系统调用就会使当前进程让出cpu,进行syscall系统调用。

// kernel/sched/core.c
SYSCALL_DEFINE0(sched_yield) {
    do_sched_yield();
    return 0;
}

系统调用通过SYSCALL_DEFINE0定义,x表示参数个数。

//  kernel/sched/core.c
static void do_sched_yield(void) {   
    ...
    schedule();
    ...
}

schedule()函数是内核中进程调度的入口。

下面我们来看看 pause 这个系统调用:

// kernel/signal.c
SYSCALL_DEFINE0(pause) {   
    __set_current_state(TASK_INTERRUPTIBLE);
    schedule();
}

// include/linux/sched.h
#define __set_current_state(state_value) \
 current->state = (state_value)

pause系统调用

先把进程设置为TASK_INTERRUPTIBLE状态,ask_struct结构体对应的state

标记为TASK_INTERRUPTIBLE后,后续进程调度中就会过忽略这个进程,选择其他进程进行调度。同样schedule()函数是内核中进程调度的入口。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
由于Linux操作系统是开源的,因此其进程调度算法的代码可以在其代码库中找到。具体来说,Linux使用完全公平调度算法(CFS)作为其默认的进程调度算法,其代码实现可以在内核源代码中的sched目录中找到。以下是一些示例代码: 1. CFS调度器代码: /* * Completely Fair Scheduler * * This file contains the code for the Completely Fair Scheduler, a * process scheduler based on a red-black tree. It implements a * proportional-share scheduling algorithm with low latency for * interactive tasks and high throughput for compute-bound tasks. * * Copyright (C) 2002-2007 Ingo Molnar <mingo@elte.hu> * Copyright (C) 2007-2011 Con Kolivas <kernel@kolivas.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ 2. 调度策略代码: /* Define a scheduling class */ static const struct sched_class fair_sched_class = { .next = &idle_sched_class, .enqueue_task = enqueue_task_fair, .dequeue_task = dequeue_task_fair, .yield_task = yield_task_fair, .check_preempt_curr = check_preempt_wakeup, .pick_next_task = pick_next_task_fair, .put_prev_task = put_prev_task_fair, #ifdef CONFIG_SMP .select_task_rq = select_task_rq_fair, .migrate_task_rq = migrate_task_rq_fair, .task_waking = task_waking_fair, .task_woken = task_woken_fair, #endif .set_curr_task = set_curr_task_fair, .task_tick = task_tick_fair, .task_fork = task_fork_fair, .task_dead = task_dead_fair, #ifdef CONFIG_FAIR_GROUP_SCHED .task_move_group = task_move_group_fair, #endif }; 3. 调度器初始化代码: void __init sched_init(void) { int i; /* Initialize the active and expired arrays for CFS */ for_each_possible_cpu(i) { struct rq *rq = cpu_rq(i); int j; /* Initialize the red-black tree for CFS */ for (j = 0; j < MAX_NICE; j++) { INIT_LIST_HEAD(&rq->cfs_rq[j].tasks); INIT_LIST_HEAD(&rq->cfs_rq[j].runnable); rb_init_node(&rq->cfs_rq[j].rb_node); } rq->cfs_rq[0].exec_clock = rq_clock(rq); rq->cfs_rq[1].exec_clock = rq_clock(rq); rq->cfs_rq[2].exec_clock = rq_clock(rq); rq->cfs_rq[3].exec_clock = rq_clock(rq); rq->cfs_rq[4].exec_clock = rq_clock(rq); rq->cfs_rq[5].exec_clock = rq_clock(rq); rq->cfs_rq[6].exec_clock = rq_clock(rq); rq->cfs_rq[7].exec_clock = rq_clock(rq); rq->cfs_rq[8].exec_clock = rq_clock(rq); rq->cfs_rq[9].exec_clock = rq_clock(rq); rq->cfs_rq[10].exec_clock = rq_clock(rq); rq->cfs_rq[11].exec_clock = rq_clock(rq); rq->cfs_rq[12].exec_clock = rq_clock(rq); rq->cfs_rq[13].exec_clock = rq_clock(rq); rq->cfs_rq[14].exec_clock = rq_clock(rq); rq->cfs_rq[15].exec_clock = rq_clock(rq); rq->nr_running = 0; rq->nr_uninterruptible = 0; rq->curr = NULL; INIT_LIST_HEAD(&rq->migration_queue); INIT_LIST_HEAD(&rq->expired); INIT_LIST_HEAD(&rq->active); rq->expired_timestamp = 0; rq->next_balance = jiffies + HZ; rq->skip_clock_update = 0; rq->idle_stamp = rq_clock(rq); rq->last_moved = jiffies; spin_lock_init(&rq->lock); spin_lock_init(&rq->task_lock); } /* Initialize the idle class */ init_idle(&init_task); init_idle(&ksoftirqd_task); init_idle(&migration_thread); /* Initialize the fair class */ sched_register_scheduler(&fair_sched_class); }

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值