- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个大致的想法,一个进程可以在ready_queue
中,CPU选择下一个要运行的候选对象。还有其他一些队列,进程在这些队列上等待(广义上来说)事件。我很早以前就从OS课程中知道,有IO和中断的等待队列。我的问题是:
进程可以等待许多事件。是否有与每个此类事件相对应的等待队列?
这些等待队列是否动态创建/销毁?如果是这样,哪个内核模块负责管理这些队列?调度程序?是否有将始终存在的预定义队列?
为了最终使等待进程脱离等待队列,内核是否有一种从每个实际事件(硬件或软件)到等待队列的映射方式,然后删除该队列上的所有进程?如果是这样,内核采用什么机制?
举个例子:
....
pid = fork();
if (pid == 0) { // child process
// Do something for a second;
}
else { // parent process
wait(NULL);
printf("Child completed.");
}
....
wait(NULL)
是阻止系统调用。我想知道父流程经历的其余旅程。我对故事情节的看法如下,如果我错过了关键步骤或如果我完全错了,请纠正我:
wait()
syscall中的任何内容。
wait(NULL)
创建一个等待队列,内核以后可以在其中找到该队列。
wait(NULL)
将父进程放入此队列,在某些映射中创建一个条目,该条目显示“如果我(内核)曾经收到软件中断,信号或任何表明子进程已完成的信息,则调度程序应查看这个等待队列”。
wait(NULL)
syscall中处于内核模式。现在,其余系统调用的主要工作是退出内核模式,并最终将父进程返回给用户。
最佳答案
让我们探索内核源代码。首先,似乎所有
各种等待例程(wait,waitid,waitpid,wait3,wait4)最终出现在
相同的系统调用wait4
。这些天,您可以在
通过查找宏SYSCALL_DEFINE1
等来查找内核
是参数的数量,对于wait4
恰好是4。
我们在自由电子Linux CrossReference中基于google的自由文本搜索最终找到了definition:
1674 SYSCALL_DEFINE4(wait4, pid_t, upid, int __user *, stat_addr,
1675 int, options, struct rusage __user *, ru)
wait4
例程进行一些参数检查,然后将它们复制到
wait_opts
do_wait()
,在同一文件中有几行:
1677 struct wait_opts wo;
1705 ret = do_wait(&wo);
1551 static long do_wait(struct wait_opts *wo)
do_wait()
将结构的另一个字段设置为函数的名称,
child_wait_callback()
是同一文件中的几行。另一个
current
。这是一个主要的“全球”,它指向
1558 init_waitqueue_func_entry(&wo->child_wait, child_wait_callback);
1559 wo->child_wait.private = current;
current->signal->wait_chldexit
:
1560 add_wait_queue(¤t->signal->wait_chldexit, &wo->child_wait);
current
。很难找到它的定义
6 #define get_current() (current_thread_info()->task)
7 #define current get_current()
163 static inline struct thread_info *current_thread_info(void)
165 return (struct thread_info *)(current_top_of_stack() - THREAD_SIZE);
55 struct thread_info {
56 struct task_struct *task; /* main task structure */
current
指向
task_struct
,我们在
sched.h中找到
1460 struct task_struct {
1461 volatile long state; /* -1 unrunnable, 0 runnable, >0 stopped */
1659 /* signal handlers */
1660 struct signal_struct *signal;
current->signal
中找到了
current->signal->wait_chldexit
,
signal_struct
在同一个文件中:
670 struct signal_struct {
677 wait_queue_head_t wait_chldexit; /* for wait4() */
add_wait_queue()
调用是指
wait_chldexit
类型的
wait_queue_head_t
结构。
struct list_head
types.h
184 struct list_head {
185 struct list_head *next, *prev;
186 };
add_wait_queue()
list_add()
wait4()
系统调用将设置一个
do_wait_thread()
:
1573 set_current_state(TASK_INTERRUPTIBLE);
1577 retval = do_wait_thread(wo, tsk);
wait_consider_task()
:
1501 static int do_wait_thread(struct wait_opts *wo, struct task_struct *tsk)
1505 list_for_each_entry(p, &tsk->children, sibling) {
1506 int ret = wait_consider_task(wo, 0, p);
schedule()
,此时该进程给出
1594 if (!signal_pending(current)) {
1595 schedule();
1596 goto repeat;
1597 }
schedule()
再次遍历所有孩子,看看是否等待
do_notify_parent()
在进程终止时被调用:
1566 * Let a parent know about the death of a child.
1572 bool do_notify_parent(struct task_struct *tsk, int sig)
1656 __wake_up_parent(tsk, tsk->parent);
__wake_up_parent()
调用
__wake_up_sync_key()
并完全使用
wait_chldexit
等待队列。
1545 void __wake_up_parent(struct task_struct *p, struct task_struct *parent)
1547 __wake_up_sync_key(&parent->signal->wait_chldexit,
1548 TASK_INTERRUPTIBLE, 1, p);
wait()
显然是其中之一
init_waitqueue_head()
调用,这是您如何初始化
kmalloc()
-空间动态创建的等待队列
DECLARE_WAIT_QUEUE_HEAD()
宏的grep查找超过150种用途
current
)排队以放弃
wake_up()
,内核即可
schedule()
)并检查硬件是否已完成操作,以及
wake_up()
调用可用于仅唤醒1个任务或全部
关于process - 进程调用syscall wait()后,谁将其唤醒?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40054413/
我正在阅读 syscall 包中的源代码,遇到了一些问题: 因为我对syscall 和assembly 完全是个菜鸟,所以不要犹豫,分享你所知道的一切:) 首先关于 func RawSyscall(t
我在一台机器上运行Docker镜像时看到以下错误 uname -r 3.10.0-229.7.2.el7.x86_64 2016/11/01 23:46:56 Error resolving sysc
不推荐使用 syscall 软件包。假设我有以下代码,希望将其迁移到不推荐使用的代码中: someGoObject := &struct{int; float32}{5, 45.4} syscall.
我正在尝试使用 VkKeyScan来自 Window 的 API,但是只要调用该函数,程序就会崩溃。我以这种方式导入和使用的其他 Window API 函数没有问题。我的 syscall.Syscal
在研究我的另一个问题时Go package syscall conn.Read() is non-blocking and cause high CPU usage , 我阅读了 syscall 包中
在 Windows 上使用 go 我有一个名为 sock 的 syscall.Handle,我想将其绑定(bind)到名为“sa”的 syscall.Sockaddr 结构中指定的地址。 如何填写 s
谁能告诉我为什么 syscall.Kill(pid, syscall.SIGSEGV) 只打印一次 "handlerSIGSEGV Sent by 0" ,但是 mustSendSIGSEGV 会打印
当我尝试在 Ubuntu 机器中启用 PPP 时,在 menuconfig 之后发生以下错误并尝试制作内核: $ sudo make make[1]: *** No rule to make targ
当我尝试在 Ubuntu 机器中启用 PPP 时,在 menuconfig 和尝试制作内核之后发生了以下错误: $ sudo make make[1]: *** No rule to make tar
我一直在尝试Go和Win32,发现了用于调用OS函数的以下两种变体(代码缩写): modUser32 = syscall.NewLazyDLL("user32.dll") procMessageBox
源代码是here 我对我的理解发表了评论 type mmapper struct { sync.Mutex active map[*byte][]byte // active mapp
这个问题在这里已经有了答案: What does a function without body mean? (1 个回答) 3年前关闭。 谁能解释一下 Go 标准库中 syscall 包中的以下代码
我目前正在尝试在 Go 上使用 user32.dll EnumWindows,但似乎无法正常工作 var( user32 = syscall.NewLazyDLL("user32.dll")
我的代码包括对 _write() 和 _sbrk() 等函数的间接调用。在项目中,我有一个名为 syscalls.c 的文件,它定义了我对这些函数的自定义实现,编译器/链接器找到了这个文件,并在我运行
我是新来的,目前正在尝试了解同事编写的一些代码 go func() { s := <-sigs if s == syscall.SIGURG { fmt.Println
我试图了解Golangs syscall软件包的一些底层细节。特别是,我对特定于Windows的系统调用感兴趣(请参见下面的示例)。 我可以找到基于UNIX的系统的syscall.Syscall()的
我有两个运行的过程,用Go语言编写,其中一个(sender.go)将消息发送到另一个(listener.go),同时通过websocket陷入for循环中。 问题是listener.go仅在终止循环后
有syscall它允许在 Linux 中进行间接系统调用。使用它的原因是什么 - 为什么它比直接调用函数更好? 最佳答案 有时内核会添加系统调用,C 库需要一段时间才能支持它们。 或者您可能正在旧的
您好 使用tkill() linux 内核调用向进程的每个线程发送信号 是否安全?因为它没有直接公开,所以我使用 syscall() 调用它。 我指的是链接 - . 但我不知道我是否应该在调用之前进行
当我创建模块时,它会发出此警告,并且会构建稍后的模块。但是如果没有实现我自己的系统调用“mycall”,构建模块有什么用 root@akshit-Vostro-1550:~/Desktop/Devic
我是一名优秀的程序员,十分优秀!