进程管理(fork)

fork - create a child process (fork函数创建子进程)


#include <unistd.h>
pid_t fork(void);
/*RETURN VALUE
       On success, the PID of the child process is returned in the parent, and
       0  is returned in the child.  On failure, -1 is returned in the parent,
       no child process is created, and errno is set appropriately.*/

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

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
int main(int arg,char *argc[])
{
    int num=10;
    pid_t pid;
    pid=fork();
    if(pid==0)
    {
        num++;
        printf("child process running,the num is %d\n",num);
        printf("pid is %d\n",getpid());
    }
    else if(pid>0)
    {
        num++;
        printf("parent process running,the num is %d\n",num);
        printf("pid is %d,pid_t 返回值为%d\n",getpid(),pid);
    }
    return 0;
}


写时复制copy on write

如果多个进程要读取它们自己的那部分资源的副本,那么复制是不必要的。

每个进程只要保存一个指向这个资源的指针就可以了。

如果一个进程要修改自己的那份资源的“副本”,那么就会复制那份资源。这就是写时复制的含义。

孤儿进程和僵尸进程

如果父进程先退出,子进程还没退出,则子进程被称为孤儿进程,如果父亲进程先结束,子进程会托孤给1号init进程。(注:任何一个进程都必须有父进程)

如果子进程先退出,父进程还没退出,那么子进程必须等到父进程捕获到了子进程的退出状态才真正结束,否则这个时候子进程就成为僵进程。

fork父子进程共享文件

#include<stdio.h>
#include<unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(int argv,char *agrc[])
{
	pid_t	 pid;	
	int fd;
	fd = open("local.txt", O_WRONLY);
	pid = fork();
	if (pid == 0)
	{
		printf("this is child pid:%d ppid:%d \n", getpid(), getppid());
		write(fd, "child\n", 6);
				
	}
	else if (pid > 0)
	{
		printf("this is parent pid:%d ppid:%d \n", getpid(), getppid());
		write(fd, "parent\n", 7);
		
	}	
	close(fd);
	return 0;
}



   对于上面的程序需要注意:在重定向父进程的标准输出时也重定向了子进程的标准输出。fork的一个特性是所有由父进程打开的文件描述符都被复制到子进程中。父、子进程每个相同的打开文件描述符共享一个文件表项。
   这种共享文件的方式使父子进程对同一文件使用了一个文件位移量。对于以下情况:一个进程fork了一个子进程,然后等待子进程终止。假定,作为普通处理的一部分,父、子进程都向标准输出执行写操作。如果父进程使其标准输出重定向(很可能是由shell实现的),那么子进程写到该标准输出时,他将更新与父进程共享的该文件的位移量。在我们所考虑的例子中,当父进程等待子进程时,子进程写到标准输出;而在子进程终止后,父进程也写入到标准输出上,并且知道其输出会添加在子进程所写数据之后。如果父、子进程不共享同一文件位移量,这种形式的交互就很难实现。


fork典型应用场景

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
int main(int arg,char *argc[])
{
    int i;
    pid_t pid;
    for(i=0; i<5; i++)
    {
        pid=fork();
        if(pid>0)
        {
            printf("pid is %d,the pid_t value is %d\n",getpid(),pid);
            printf("current parent process is done\n");
            exit(0);
        }
    }
    return 0;
}



#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
int main(int arg,char *argc[])
{
    int i;
    pid_t pid;
    for(i=0; i<10; i++)
    {
        pid=fork();
        if(pid==0)
        {
            printf("the num%d child process is running\n",i+1);
            exit(0);
        }
    }
    return 0;
}


猜你喜欢

转载自blog.csdn.net/qq_33506160/article/details/80330762