函数getrlimit和setrlimit:每个进程都有一组资源限制,可以用这两个函数查看修改。
在更改资源限制时要注意:
1.任何进程都可将一个软限制值更改为小于或等于其硬限制值
2.任何进程都可降低其硬限制值,但必须大于等于其软限制值
3.只有超级用户可以提高硬限制值
两个函数的resource参数取下列值之一:
每个进程都有一个非负整型表示的唯一进程ID,系统有一些专用进程,ID为0的进程通常是调度进程,常被称为交换进程,是内核的一部分。进程ID1通常是init进程,此进程负责在自举内核后启动第一个unix系统。init进程不会终止。
函数fork:
一个现有的进程可以调用fork函数创建一个新进程。
由fork创建的新进程称为子进程,子程序是父进程的副本,获得父进程的数据空间,堆和栈的副本。父和子进程并不共享这些存储空间。
下列程序演示了fork函数,可以看出子进程对变量做的改变并不影响进程中变量的值。
#include "apue.h"
int globvar =6;
char buf[]="a write to stdout\n";
int main()
{
int var;
pid_t pid;
var = 88;
if(write(STDOUT_FILENO, buf ,sizeof(buf)-1) !=sizeof(buf)-1)
err_sys("write error");
printf("before fork\n");
if((pid=fork())<0)
{
err_sys("fork error");
}
else if(pid == 0) //子进程
{
globvar++;
var++;
}
else
//父进程
{
sleep(2);
}
printf("pid = %ld , glob =%d, var =%d\n",(long)getpid(),globvar,var);
exit(0);
}
一般而言,在fork之后是父进程先执行还是子进程先执行是不确定的,取决于内核的调度算法,在上程序中,父进程休眠2s,让子进程先执行。
vfork函数:
调用序列和返回值与fork相同,但两者的语义不同。vfork用于创建一个新进程,而该进程的目的是exec一个新程序,与fork的区别在于,vfork不会将父进程的地址空间完全复制到子进程中,因为子进程会立即调用exec,于是也就不会引用该地址空间。还有一个区别就是,vfork保证子进程先运行,在它调用exec或exit之后父进程才可能被调度运行。
函数exit:
之前提过了集中正常终止和异常终止进程的方式,对于任意一种,都希望能够通知父进程是如何终止的,对于正常终止的,将其退出状态作为参数传送给函数,异常终止的,内核产生一个指示原因的终止状态。在fork函数可知道,子进程是父进程调用fork产生的,如果父进程在子进程之前终止,这些子进程的父进程都改变成为init进程,称这些进程由init进程收养。
如果子进程在父进程之前终止,父进程如何得到子进程的终止状态?内核为每个终止子进程保存了信息,当父进程调用wait或waitpid时,可以得到这些信息,如果一个已经终止,但父进程未对其进行善后处理(获取终止子进程的有关信息,释放它仍占用的内存)的进程被称为僵死进程(zombie)
被init进程收养的子进程终止会怎么样?init是无论何时只要有一个子进程终止,init就会调用一个wait函数取得其终止状态,这样就防止了在系统中塞满僵死进程。
函数wait和waitpid:
当一个进程正常或异常终止时,内核向父进程发送sigchld信号,父进程可以选择忽略该信号,或者提供给一个该信号发生即被调用执行的函数。
如果调用wait/waitpid进程会发生什么?
如果其所有进程都还在运行,则阻塞
如果一个子进程已终止,正等待父进程获取其终止状态,则取得终止状态立即返回。
如果没有任何子进程,立即出错返回。
两个函数的区别如下:
在一个子进程终止前,wait使其调用者阻塞,而waitpid有一选项,可使调用者不阻塞
waitpid并不等待在其调用后的第一个终止子进程,它有若干选项,可以控制它所等待的进程。
函数wait3和wait4
这两个函数提供的功能更多,这与附加参数有关。该参数允许内核返回由终止进程及其所有子进程使用的资源概况。
竞争条件:
当多个进程都企图对共享数据进行某种处理时,而最后的结果又取决于进程运行的顺序时。就发生了竞争条件。
函数exec:当用fork创建新的子进程时,子进程往往要调用exec函数以执行另一个进程,当进程调用exec时,该进程执行的程序完全替代为新程序,而新程序从main函数开始执行。