摘录:
子进程继承了父进程的几乎所有的属性:
. 实际UID,GID和有效UID,GID.
. 环境变量.
. 附加GID.
. 调用exec()时的关闭标志.
. UID设置模式比特位.
. GID设置模式比特位.
. 进程组号.
. 会话ID.
. 控制终端.
. 当前工作目录.
. 根目录.
. 文件创建掩码UMASK.
. 文件长度限制ULIMIT.
. 预定值, 如优先级和任何其他的进程预定参数, 根据种类不同
决定是否可以继承.
. 还有一些其它属性.
但子进程也有与父进程不同的属性:
. 进程号, 子进程号不同与任何一个活动的进程组号.
. 父进程号.
. 子进程继承父进程的文件描述符或流时, 具有自己的一个拷贝
并且与父进程和其它子进程共享该资源.
. 子进程的用户时间和系统时间被初始化为0.
. 子进程的超时时钟设置为0.
. 子进程的信号处理函数指针组置为空. (该处有问题。)
子进程继承父进程的处理函数(当一个进程调用fork时,因为子进程在开始时复制父进程的存储映像,信号捕捉函数的地址在子进程中是有意义的,所以子进程继承父进程的信号处理函数。
特殊的是exec,因为exec运行新的程序后会覆盖从父进程继承来的存储映像,那么信号捕捉函数在新程序中已无意义,所以exec会将原先设置为要捕捉的信号都更改为默认动作。)
. 子进程不继承父进程的记录锁.
返回值: 调用成功则对子进程返回0, 对父进程返回子进程号, 这也是
最方便的区分父子进程的方法. 若调用失败则返回-1给父进程,
子进程不生成.
例子:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <signal.h> static void pExit () { printf("func [%d][%d]\n",getppid(),getpid()); } static void pAlarm () { printf("alarm [%d][%d]\n",getppid(),getpid()); } main() { pid_t pid; struct sigaction act; int status; printf("test parent pid[%d]\n",getpid()); act.sa_handler = (void (*)()) pExit; sigemptyset (&act.sa_mask); act.sa_flags = 0; sigaction (SIGUSR1, &act, NULL); act.sa_handler = (void (*)()) pAlarm; sigemptyset (&act.sa_mask); act.sa_flags = 0; sigaction (SIGALRM, &act, NULL); pid = fork(); if (pid == 0) { printf("test pid[%d]\n",getpid()); kill (getpid(), SIGUSR1); alarm(1); sleep(2); exit (0); } pid = wait(&status); printf("test =[%d]\n",status); }
输出:
test parent pid[27188] test pid[27189] func [27188][27189] alarm [27188][27189] test =[0]
可见时钟信号虽然清0,但是处理函数安装后是不变的.
|
阅读(5075) | 评论(0) | 转发(0) |