计算机的cpu越来越廉价,在一些需要大量计算的公司和科研单位,集成机器(cluster)也变得很普遍。这就会引出了一个问题,怎么安排任务才能让这么多cpu得到充分的利用?这个问题其实早就有人考虑到了, PBS就是用来批量提交任务的程序。PBS功能强大,但是未必就能够满足所有要求。
要编写个性化的进程管理程序需要了解在Lunix/unix下面已经包括了的进程编程所需要的库函数。简单的说,首先可以通过fork()函数生成子进程。调用fork()后会有两个返回,子进程如果成功生成会返回0,父进程返回的是PID。然后可以调用exec族函数,将子进程替换成所要执行的程序。进程在执行完后并会留下僵尸(zombie)进程,可以使用wait()函数返回执行情况并完全释放资源。关于进程编程有一个完整的教程----《系统调用跟我学:1,2,3,4》。
以下这个小程序展示如何生成一个进程,执行任务,并且当任务完成后捕捉到子进程的信息。
/* One process program */ /* This sample shows how to use fork(),execlp() and waitpid() */ #include <sys/types.h> #include <sys/wait.h> #include <unistd.h> #include <stdlib.h> #include <stdio.h> main() { pid_t pc, pr; pc=fork(); if(pc<0) printf("Error occured on forking./n"); else if(pc==0){ /* open /etc/hosts with nedit */ execlp("nedit", "nedit","/etc/hosts", NULL); exit(0); } do{ pr=waitpid(pc, NULL, WNOHANG); if(pr==0){ printf("No child exited/n"); sleep(1); } }while(pr==0); if(pr==pc) printf("successfully get child %d/n", pr); else printf("some error occured/n"); } 对于多个进程的情况,还需要学习关于信号的知识。因为进程一旦调用了wait,就立即阻塞自己。而采用信号处理程序(signal handler)就能够避开这个缺点。关于信号处理可以参考《 Introduction To Unix Signals Programming》,关于多进程编程可以参考《 Unix Multi-Process Programming and Inter-Process Communications (IPC)》。 下面这个程序展示了如何产生两个进程,在二十秒之内有进程退出后就提交指定任务。 /* multi process program */ /* This sample shows how to fork two procss */ /* and submit new task once there is task finished */ /* in a period of time */ #include <sys/types.h> #include <sys/wait.h> #include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <signal.h> void catch_child(int sig_num) { int child_status; pid_t pc, pr; pr=wait(&child_status); printf("child %d exited./n",pr); pc=fork(); if(pc<0) printf("Error occured on forking./n"); else if(pc==0){ /* open /etc/hosts with nedit */ execlp("nedit", "nedit","/etc/hosts", NULL); exit(0); } } main() { signal(SIGCHLD, catch_child); int child_pid[2]; int i,j; for(j=0;j<2;j++){ /* generates two child-process */ child_pid[j] = fork(); switch (child_pid[j]) { case -1: perror("fork"); exit(1); case 0: printf("hello world/n"); sleep(5); /* sleep a little, so we'll have */ /* time to see what is going on */ exit(0); default: break; } } for (j=0; j<20; j++) { printf("%d/n", j); sleep(1); /* sleep for a second, so we'll have time to see the mix */ } }