进程的终结大部分都要靠 exit() 来完成的,最终的系统调用为 do_exit()。asmlinkage long sys_exit(int error_code)
{
do_exit((error_code&0xff)<<8);
}
/*当cpu进入到do_exit后,当前进程就会在中途寿终正寝,不会从这个函数中返回,当然也就不会从sys_exit
中返回,从而也就不会从系统调用exit()中返回*/
fastcall NORET_TYPE void do_exit(long code)
{
...
WARN_ON(atomic_read(&tsk->fs_excl));
/*由于中断服务程序根本不应该调用do_exit,不管是直接还是间接,所以首先通过in_interrupt进行加以检查
若发现是在某个中断服务程序中调用的,那就一定是出了问题*/
if (unlikely(in_interrupt()))
panic("Aiee, killing interrupt handler!");
...
/*current->flags的PF_EXITING标志表示进程正在被删除 */
if (unlikely(tsk->flags & PF_EXITING)) {
printk(KERN_ALERT
"Fixing recursive fault but reboot is needed!\n");
...
tsk->flags |= PF_EXITPIDONE; /* 设置进程标识为PF_EXITPIDONE*/
if (tsk->io_context)
exit_io_context();
/* 设置进程状态为不可中断的等待状态 */
set_current_state(TASK_UNINTERRUPTIBLE);
/* 调度其它进程 */
schedule();
}
tsk->flags |= PF_EXITING;
/* 内存屏障,用于确保在它以后的操做开始执行以前,它以前的操做已经完成 */
smp_mb();
spin_unlock_wait(&tsk->pi_lock);
...
//清除定时器
group_dead = atomic_dec_and_test(&tsk->signal->live);//live用来表示线程组中活动进程的数量
if (group_dead) { //当没有活动的进程时
exit_child_reaper(tsk);
//取消高精度定时器
hrtimer_cancel(&tsk->signal->real_timer);
//删除POSIX.1b类型的定时器
exit_itimers(tsk->signal);
}
//收集进程会计信息
acct_collect(code, group_dead);
...
//设置终止代码
tsk->exit_code = code;
taskstats_exit(tsk, group_dead);
//释放线性区描述符和页表
exit_mm(tsk);
if (group_dead)
acct_process();
//遍历current->sysvsem.undo_list链表,并清除进程所涉及的每个IPC信号量的操作痕迹
exit_sem(tsk);
//释放文件对象相关资源
__exit_files(tsk);
//释放struct fs_struct结构体
__exit_fs(tsk);
//检查有多少未使用的进程内核栈
check_stack_usage();
exit_thread();
cgroup_exit(tsk, 1);
exit_keys(tsk);
if (group_dead && tsk->signal->leader)
disassociate_ctty(1);
module_put(task_thread_info(tsk)->exec_domain->module);
if (tsk->binfmt)
module_put(tsk->binfmt->module);
proc_exit_connector(tsk);
//给父进程发送信号,让其知道子进程生命已经结束,来料理子进程的后事. 同时把进程状态exit_state 设置成 EXIT_ZOMBIE
exit_notify(tsk);
...
tsk->flags |= PF_EXITPIDONE;
...
preempt_disable();
/* causes final put_task_struct in finish_task_switch(). */
tsk->state = TASK_DEAD;
/*do_exit 不返回的真正原因在这里,由于进程状态设置成了EXIT_ZOMBIE,使得该进程永远不会再被选中进行调度,所以
也就不会使用schedule()调度别的进程后从schedule中返回。因此只能等父进程收到子进程发送的信号来处理子进程,并将
子进程的task_struct结构释放掉,子进程最终从系统中消失。而父进程在wait4(对应系统函数sys_wait4)中等待着。
*/
schedule();
BUG();
/* Avoid "noreturn function does return". */
for (;;)
cpu_relax(); /* For when BUG is null */
}
该进程目前所占用的内存资源就是内核栈、thread_info 结构和 task_struct 结构。此时进程存在的唯一目的就是向它的父进程提供信息。父进程检索到信息后,或者通知内核它不关心那些无关的信息后,子进程的这些剩余资源才被释放归还给系统。asmlinkage long sys_wait4(pid_t pid, int __user *stat_addr,
int options, struct rusage __user *ru)
{
long ret;
if (options & ~(WNOHANG|WUNTRACED|WCONTINUED|
__WNOTHREAD|__WCLONE|__WALL))
return -EINVAL;
ret = do_wait(pid, options | WEXITED, NULL, stat_addr, ru);
/* avoid REGPARM breakage on x86: */
prevent_tail_call(ret);
return ret;
}sys_wait4
--> do_wait
--> wait_task_zombie
--> release_taskvoid release_task(struct task_struct * p)
{
struct task_struct *leader;
int zap_leader;
repeat:
...
/* 1)该函数调用_unhash_process(),后者调用detach_pid()从pidhash
• 上删除该进程,同时也要从任务列表中删除该进程
• 2)释放目前僵死进程所使用的所有剩余资源,并进行最终统计和记录
*/
__exit_signal(p);
/*
• If we are the last non-leader member of the thread
• group, and the leader is zombie, then notify the
• group leader's parent process. (if it wants notification.)
*/
zap_leader = 0;
leader = p->group_leader;
/*若该进程是线程组最后一个进程,并且领头进程已经死掉,,则通知僵死的领头进程的父进程 /
if (leader != p && thread_group_empty(leader) && leader->exit_state == EXIT_ZOMBIE) {
BUG_ON(leader->exit_signal == -1);
do_notify_parent(leader, leader->exit_signal);
/
• If we were the last child thread and the leader has
• exited already, and the leader's parent ignores SIGCHLD,
• then we are the one who should release the leader.
•
• do_notify_parent() will have marked it self-reaping in
• that case.
*/
zap_leader = (leader->exit_signal == -1);
}
write_unlock_irq(&tasklist_lock);
release_thread(p);
//调用 put_task_struct 释放进程内核栈和thread_info结构所占的页,并释放task_struct 所占的slab告诉缓存。
call_rcu(&p->rcu, delayed_put_task_struct);
p = leader;
if (unlikely(zap_leader))
goto repeat;
}我正在使用i18n从头开始构建一个多语言网络应用程序,虽然我自己可以处理一大堆yml文件,但我说的语言(非常)有限,最终我想寻求外部帮助帮助。我想知道这里是否有人在使用UI插件/gem(与django上的django-rosetta不同)来处理多个翻译器,其中一些翻译器不愿意或无法处理存储库中的100多个文件,处理语言数据。谢谢&问候,安德拉斯(如果您已经在rubyonrails-talk上遇到了这个问题,我们深表歉意) 最佳答案 有一个rails3branchofthetolkgem在github上。您可以通过在Gemfi
在MRIRuby中我可以这样做:deftransferinternal_server=self.init_serverpid=forkdointernal_server.runend#Maketheserverprocessrunindependently.Process.detach(pid)internal_client=self.init_client#Dootherstuffwithconnectingtointernal_server...internal_client.post('somedata')ensure#KillserverProcess.kill('KILL',
我正在编写一个gem,我必须在其中fork两个启动两个webrick服务器的进程。我想通过基类的类方法启动这个服务器,因为应该只有这两个服务器在运行,而不是多个。在运行时,我想调用这两个服务器上的一些方法来更改变量。我的问题是,我无法通过基类的类方法访问fork的实例变量。此外,我不能在我的基类中使用线程,因为在幕后我正在使用另一个不是线程安全的库。所以我必须将每个服务器派生到它自己的进程。我用类变量试过了,比如@@server。但是当我试图通过基类访问这个变量时,它是nil。我读到在Ruby中不可能在分支之间共享类变量,对吗?那么,还有其他解决办法吗?我考虑过使用单例,但我不确定这是
我安装了ruby版本管理器,并将RVM安装的ruby实现设置为默认值,这样'哪个ruby'显示'~/.rvm/ruby-1.8.6-p383/bin/ruby'但是当我在emacs中打开inf-ruby缓冲区时,它使用安装在/usr/bin中的ruby。有没有办法让emacs像shell一样尊重ruby的路径?谢谢! 最佳答案 我创建了一个emacs扩展来将rvm集成到emacs中。如果您有兴趣,可以在这里获取:http://github.com/senny/rvm.el
是否有简单的方法来更改默认ISO格式(yyyy-mm-dd)的ActiveAdmin日期过滤器显示格式? 最佳答案 您可以像这样为日期选择器提供额外的选项,而不是覆盖js:=f.input:my_date,as::datepicker,datepicker_options:{dateFormat:"mm/dd/yy"} 关于ruby-on-rails-事件管理员日期过滤器日期格式自定义,我们在StackOverflow上找到一个类似的问题: https://s
我正在尝试使用以下代码通过将ffmpeg实用程序作为子进程运行并获取其输出并解析它来确定视频分辨率:IO.popen'ffmpeg-i'+path_to_filedo|ffmpegIO|#myparsegoeshereend...但是ffmpeg输出仍然连接到标准输出并且ffmepgIO.readlines是空的。ffmpeg实用程序是否需要一些特殊处理?或者还有其他方法可以获得ffmpeg输出吗?我在WinXP和FedoraLinux下测试了这段代码-结果是一样的。 最佳答案 要跟进mouviciel的评论,您需要使用类似pope
我想用这两种语言中的任何一种(最好是ruby)制作一个窗口管理器。老实说,除了我需要加载某种X模块外,我不知道从哪里开始。因此,如果有人有线索,如果您能指出正确的方向,那就太好了。谢谢 最佳答案 XCB,X的下一代API使用XML格式定义X协议(protocol),并使用脚本生成特定语言绑定(bind)。它在概念上与SWIG类似,只是它描述的不是CAPI,而是X协议(protocol)。目前,C和Python存在绑定(bind)。理论上,Ruby端口只是编写一个从XML协议(protocol)定义语言到Ruby的翻译器的问题。生
我目前正在用Ruby编写一个项目,它使用ActiveRecordgem进行数据库交互,我正在尝试使用ActiveRecord::Base.logger记录所有数据库事件具有以下代码的属性ActiveRecord::Base.logger=Logger.new(File.open('logs/database.log','a'))这适用于迁移等(出于某种原因似乎需要启用日志记录,因为它在禁用时会出现NilClass错误)但是当我尝试运行包含调用ActiveRecord对象的线程守护程序的项目时脚本失败并出现以下错误/System/Library/Frameworks/Ruby.frame
这是我在ActiveAdmin中的自定义页面ActiveAdmin.register_page"Settings"doaction_itemdolink_to('Importprojects','settings/importprojects')endcontentdopara"Text"endcontrollerdodefimportprojectssystem"rakedataspider:import_projects_ninja"para"OK"endendend我想做的是,当我单击“导入项目”按钮时,我想在Controller中执行rake任务。但是我无法访问该方法。可能是什
我想从rubyrake脚本运行一个可执行文件,比如foo.exe我希望将foo.exe的STDOUT和STDERR输出直接写入我正在运行rake任务的控制台.当进程完成时,我想将退出代码捕获到一个变量中。我如何实现这一目标?我一直在玩backticks、process.spawn、system但我无法获得我想要的所有行为,只有部分更新:我在Windows上,在标准命令提示符下,而不是cygwin 最佳答案 system获取您想要的STDOUT行为。它还返回true作为零退出代码,这可能很有用。$?填充了有关最后一次system调