进程(二)

1.fork()

fork创建一个新进程。这个系统调用复制当前进程,在进程表中创建一个新的表项,新进程几乎与原进程一模一样,执行的代码也是完全一样,但新进程有自己的数据空间、环境、文件描述符。

#include<sys/types.h>
#include<unistd.h>
pid_t fork(void);
返回值:
  • 如果成功创建一个子进程,对于父进程来说返回子进程ID
  • 如果成功创建一个子进程,对于子进程来说返回值为0
  • 如果为-1表示创建失败

  1. 使用fork函数得到的子进程从父进程的继承了整个进程的地址空间,包括:进程上下文、进程堆栈、内存信息、打开的文件描述符、信号控制设置、进程优先级、进程组号、当前工作目录、根目录、资源限制、控制终端等。
  2. 子进程与父进程的区别在于:

    • 1、父进程设置的锁,子进程不继承
    • 2、各自的进程ID和父进程ID不同
    • 3、子进程的未决告警被清除;
    • 4、子进程的未决信号集设置为空集。
     3.  fork系统调用需要注意的地方

    • fork系统调用之后,父子进程将交替执行。
    • 如果父进程先退出,子进程还没退出那么子进程的父进程将变为init进程。(注:任何一个进程都必须有父进程)
    • 如果子进程先退出,父进程还没退出,那么子进程必须等到父进程捕获到了子进程的退出状态才真正结束,否则这个时候子进程就成为僵进程。
    • 子进程退出会发送SIGCHLD信号给父进程,可以选择忽略或使用信号处理函数接收处理就可以避免僵尸进程。
一个fork的例子
/*fork.c*/
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
int main()
{
    pid_t pid;
    char *message;
    pid=fork();
    if(pid<0)
    {
	perror("fork error!");
	exit(1);
    }
    else if(pid>0)
    {
	message="this is parent!";
	printf("%s ppid=%d\n",message,pid);
    }
    else
    {
	message="this is child!";
	printf("%s ppid=%d\n",message,pid);
    }
    return 0;
}


make fork
./fork1
结果是:
this is parent! ppid=2486
zhou@hyn-virtual-machine:~/os/test/test1/daemon$ this is child! ppid=0
委屈结果是乱的,别急我们来看第二个函数;

2.wait()

在例程fork1.c中由于父进程先于子进程结束;所以输出结果有点乱,我们可以在父进程中调用wait()等待子进程结束;

#include<sys/types.h>
#include<sys/wait.h>
pid_t wait(int *stat_loc);

wait()会暂时停止进程的执行,直到有信号来到或子进程结束。如果在调用wait()时子进程已经结束,则wait()会立即返回子进程结束状态值。子进程的结束状态值会由参数status 返回,而子进程的进程识别码也会一起返回。如果不在意结束状态值,则参数status 可以设成NULL。

结束状态值信息:

  • WIFEXITED(stat_val)如果子进程正常结束,他就取一个非零值
  • WEXITSTATUS(stat_val)如果WIFEXITED非零,他返回子进程的退出码
  • WIFSIGNALED(stat_val)如果子进程因为一个未捕获的信号而终止,他就取一个非零值
  • WTERMSIG(stat_val)如果WIFSIGNALED非零,他返回一个信号代码
  • WIFSTOPPED(stat_val)如果子进程意外终止,它就取一个非零值
  • WSTOPSIG(stat_val)如果WIFSTOPPED非零,他返回一个信号代码

一个wait的例子

/*wait.c*/
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/wait.h>
int main()
{
    pid_t pid;
    char *message;
    pid=fork();
    int exit_code;
    if(pid<0)
    {
		perror("fork error!");
		exit(1);
    }
    else if(pid>0)
    {
		message="this is parent!";
		printf("%s ppid=%d\n",message,pid);
		int stat_val;
		pid_t child_pid;

		child_pid=wait(&stat_val);
		if(WIFEXITED(stat_val))
		{
			printf("child exited with code%d\n",WEXITSTATUS(stat_val));
		}
		else
		{
			printf("child terminated abnormally\n");
		}
    }
    else
    {
		message="this is child!";
		printf("%s ppid=%d\n",message,pid);
		exit_code=37;
    }
    exit(exit_code);
}

make wait
./wait

结果是
this is parent! ppid=2576
this is child! ppid=0
child exited with code37
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值