linux进程管理(C语言)

理解进程控制的原理对于理解和修改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

努力爱一个人。付出,不一定会有收获;

linux进程管理(C语言)

相关文章:

你感兴趣的文章:

标签云: