理解进程控制的原理对于理解和修改fioproject非常的重要。"fio is an I/O tool meant to be used both for benchmark and stress/hardware verification."
进程
unix
创建进程
每一个进程都有一个正数的
fork
exit
父进程和子进程是并发运行的独立进程。内核能够以任意方式交替执行他们的逻辑控制流中的指令。
如果能够在
关于这个,fio这个程序利用到它的地方就是
while(todo){
structthread_data*map[REAL_MAX_JOBS];
structtimevalthis_start;
intthis_jobs=0,left;
for_each_td(td,i){
if(td->runstate!=TD_NOT_CREATED)
continue;
if(td->o.start_delay){
spent=utime_since_genesis();
if(td->o.start_delay>spent)
continue;
}
if(td->o.stonewall&&(nr_started||nr_running)){
dprint(FD_PROCESS,"%s:stonewallwait\n",
td->o.name);
break;
}
init_disk_util(td);
td->rusage_sem=fio_mutex_init(FIO_MUTEX_LOCKED);
td->update_rusage=0;
/*
*Setstatetocreated.Threadwilltransition
*toTD_INITIALIZEDwhenit’sdonesettingup.
*/
td_set_runstate(td,TD_CREATED);
map[this_jobs++]=td;
nr_started++;
…
if(td->o.use_thread){
intret;
dprint(FD_PROCESS,"willpthread_create\n");
ret=pthread_create(&td->thread,NULL,
thread_main,td);
if(ret){
log_err("pthread_create:%s\n",
strerror(ret));
nr_started–;
break;
}
ret=pthread_detach(td->thread);
if(ret)
log_err("pthread_detach:%s",
strerror(ret));
}else{
pid_tpid;
dprint(FD_PROCESS,"willfork\n");
pid=fork();
if(!pid){
intret=fork_main(shm_id,i);
_exit(ret);
}elseif(i==fio_debug_jobno)
*fio_debug_jobp=pid;
}
这就相当于这么编程:
#include<stdio.h>
intmain()
{
inti=1;
intpid;
while((i–)>=0){
pid=fork();
if(pid==0){
i–;
printf("inthechildprocess.\n");
}
else
printf("intheparentprocess.\n");
}
}
编译并执行上面那段程序的结果:
root@localhost~]#./a.out
intheparentprocess.
inthechildprocess.
intheparentprocess.
inthechildprocess.
一共创建了两个进程,只不过在
note:threadmain这个函数做了许多事情,会再分析。
回收子进程
当一个进程由于某种原因终止时,内核并不是立即把它从系统中清除。相反,进程被保持在一种已终止的状态中,直到被它的父进程
一个终止了但未被回收的进程称为僵尸zombie。
如果父进程没有回收他的
一个进程可以通过调用waitpid函数来等待它的子进程终止或者停止。
函数原型:
#include<sys/wait.h> 定义函数pid_twaitpid(pid_tpid,int*status,intoptions);
waitpid-函数说明
waitpid()会暂时停止目前进程的执行,直到有信号来到或子进程 结束。如果在调用waitpid()时子进程已经结束,则waitpid()会立即 返回子进程结束状态值。子进程的结束状态值会由参数status返回, 而子进程的进程识别码也会一起返回。如果不在意结束状态值,则 参数status可以设成NULL。参数pid为欲等待的子进程识别码, 其他数值意义如下: pid<-1等待进程组识别码为pid的任何子进程。 pid=-1等待任何子进程,相当于wait()。 pid=0等待进程组识别码与目前进程相同的任何子进程。 pid>0等待任何子进程识别码为pid的子进程。 参数options提供了一些额外的选项来控制waitpid,参数option可以为0或可以用"|"运算符把它们连接起来使用,比如: ret=waitpid(-1,NULL,WNOHANG|WUNTRACED); 如果我们不想使用它们,也可以把options设为0,如: ret=waitpid(-1,NULL,0); WNOHANG若pid指定的子进程没有结束,则waitpid()函数返回0,不予以等待。若结束,,则返回该子进程的ID。 WUNTRACED若子进程进入暂停状态,则马上返回,但子进程的结束状态不予以理会。WIFSTOPPED(status)宏确定返回值是否对应与一个暂停子进程。 子进程的结束状态返回后存于status,底下有几个宏可判别结束情况: WIFEXITED(status)如果若为正常结束子进程返回的状态,则为真;对于这种情况可执行WEXITSTATUS(status),取子进程传给exit或_eixt的低8位。 WEXITSTATUS(status)取得子进程exit()返回的结束代码,一般会先用WIFEXITED来判断是否正常结束才能使用此宏。 WIFSIGNALED(status)若为异常结束子进程返回的状态,则为真;对于这种情况可执行WTERMSIG(status),取使子进程结束的信号编号。 WTERMSIG(status)取得子进程因信号而中止的信号代码,一般会先用WIFSIGNALED来判断后才使用此宏。 WIFSTOPPED(status)若为当前暂停子进程返回的状态,则为真;对于这种情况可执行WSTOPSIG(status),取使子进程暂停的信号编号。 WSTOPSIG(status)取得引发子进程暂停的信号代码,一般会先用WIFSTOPPED来判断后才使用此宏。 如果执行成功则返回子进程识别码(PID),如果有错误发生则返回 返回值-1。失败原因存于errno中。
fio使用waitpid的例子
*Runoverthejobmapandreapthethreadsthathaveexited,ifany.
*/
staticvoidreap_threads(unsignedint*nr_running,unsignedint*t_rate,
unsignedint*m_rate)
{
…
realthreads=pending=cputhreads=0;
for_each_td(td,i){
intflags=0;
/*
*->io_opsisNULLforathreadthathasclosedits
*ioengine
*/
if(td->io_ops&&!strcmp(td->io_ops->name,"cpuio"))
cputhreads++;
else
realthreads++;
…
flags=WNOHANG;
if(td->runstate==TD_EXITED)
flags=0;
/*
*checkifsomeonequitorgotkilledinanunusualway
*/
ret=waitpid(td->pid,&status,flags);
if(ret<0){
if(errno==ECHILD){
log_err("fio:pid=%ddisappeared%d\n",
(int)td->pid,td->runstate);
td->sig=ECHILD;
td_set_runstate(td,TD_REAPED);
gotoreaped;
}
perror("waitpid");
}elseif(ret==td->pid){
if(WIFSIGNALED(status)){
intsig=WTERMSIG(status);
if(sig!=SIGTERM&&sig!=SIGUSR2)
log_err("fio:pid=%d,gotsignal=%d\n",
(int)td->pid,sig);
td->sig=sig;
td_set_runstate(td,TD_REAPED);
gotoreaped;
}
if(WIFEXITED(status)){
if(WEXITSTATUS(status)&&!td->error)
td->error=WEXITSTATUS(status);
td_set_runstate(td,TD_REAPED);
gotoreaped;
}
}
…
让进程休眠
sleep
另外一个有用的函数是pause,该函数让调用函数休眠,直到该进程收到一个信号。
进程间的信号传递
note:由于时间关系,有空再补充。
参考文献
Caapp:深入理解计算机系统
源码fio-2.1.10
努力爱一个人。付出,不一定会有收获;