码迷,mamicode.com
首页 > 系统相关 > 详细

子进程

时间:2016-06-27 00:11:17      阅读:254      评论:0      收藏:0      [点我收藏+]

标签:进程   子进程   文件描述符   

  1.fork()函数     include<unistd.h>

     一个现有进程可以调用fork函数穿件一个新进程,子进程返回0,父进程返回子进程ID,出错返回-1

     子进程是父进程的副本,子进程获得父进程的数据空间、堆和栈的副本,父子进程不共享这些空间。父子进程共享正文段。对于子进程,现在很多实现并不执行父进程的数据段。栈和堆的完全复制,而是使用写时拷贝技术,这些区域由父子进程共享,而且内核将他们的访问权限变为只读。若父子进程中任意个试图修改这些区域,则内核只为修改区域的那块内存制作一个副本。

例1:

技术分享

直接输出

技术分享

将fork2输出内容重定位到文件中

技术分享

   fork的一个特性是父进程的所有打开文件描述符都被复制到子进程中。父进程每个相同的打开描述符共享一个文件表项

例2

技术分享

技术分享

 创建子进程后,多了一个进程(多了一套PCB),调度器选择一个进程执行,具体谁先运行,只有调度器知道,但是我们希望子进程先结束(僵尸进程),若父进程先结束则会导致孤儿进程

     父进程和子进程有一块共享的代码区(fork完后不做任何事情),数据不共享(写实拷贝技术-->任意进程试图)

*物理地址到虚拟地址--》页表和MMU,MMU->硬件,系统只有一个,

     

     父子进程之间区别:1.fork返回值不同(父进程返回子进程pid子进程返回1)

                                   2.进程ID不同

                                   3.具有不同的父进程ID

                                   4.子进程的tms_utime  tms_stime  tms_cuitime  tms_ustime均被置为0

                                   5.子进程设置的文件锁不会被子进程继承

                                   6.子进程未处理闹钟被清除

                                   7.子进程的未处理信号集被设置为空集

     fork用法:1.一个进程需要复制自己,使父子进程同时执行不同的代码(父进程等待客户端请求,生成子进程  

                         来处理请求)

                    2.一个进程要执行一个不同的程序(子进程从fork返回后调用exec函数)

     fork调用失败原因:

                    1.系统中太多进程

                    2.实际用户进程数超过限制。

     2.文件描述符文件指针

     在上面例1中,我们提到了文件描述符。fork的父进程的所有打开文件描述符都被复制到子进程中。父子进程的每个相同的打开描述符共享一个文件表项。

     文件描述符是一个整形,文件指针是一个指针。

     进程在创建时默认打开三个文件:标准输入。标准输出和标准错误(stdin,stdout,stderr),标准输入设备一般是键盘,标准输出设备一般是键盘显示器。

     文件描述符返回的是整形,这个整数是个小整数,其他文件是从3开始(标准输入0,标准输出1,标准错误2,是系统默认打开的,库函数不能干涉),且按顺序排序,若关掉0和2,则其他文件从0开始,但是没有1(因为1被占用)且和打开文件顺序有关,只要打开文件,就会有文件描述符,打开错误返回-1

     文件描述符表其实就是一个数组,文件描述符就是数组下标。

     在以前打开文件时我们这么写 :FILE *pf=fopen(‘./log‘,‘r‘);

     查看fopen:  

技术分享

 fopen是C标准库的库函数。fp即为文件指针。

      open是系统调用,open返回int,打印成功返回文件描述符(整数),返回失败返回-1

技术分享

open的模式字段有:O_RDONLY(open_readonly只读)、O_WRONLY、O_RDWR....当文件不存在可以使用O_CREAT创建

    *库函数和系统调用:系统调用是操作系统提供的接口,C库是基于系统调用接口做的二次开发,时操作更简便

    

     printf和fwrite

技术分享

write和fwrite

技术分享

例3 open和fopen

技术分享

gcc编译后运行可执行文件,当前目录下会产生一个log.txt文件

技术分享

由于上面程序中没有修改权限导致这个文件权限为S,当在open函数参数后面加上“0644”权限被改为:

技术分享

例4 write和fwrite


int main()

{

char *p="hello word";

write(1,p.strlen(p));//打印到标准输出

char*msg="hello"

fwrite(msg,1,strlen(msg),std);//标准输出设备

}

例5 关于缓冲区

技术分享技术分享

技术分享将本来输出到屏幕输出到文件中

技术分享

    printf,fwrite会打印两次。 只要用库函数,都有缓冲区,在标准输出上直接被刷出来,所以若重定位到文件中,全缓冲,遇到\n不会被甩出来,printf调用完毕,输出内容被保存到父进程的缓冲区,由于父子进程不共享数据区,若有谁想修改数据区,系统不允许修改,fork参照父进程来创建,子进程缓冲区的数据和父进程相同,当父子进程退出,会强制刷一份缓冲区内容。,标准输出是行缓冲,\n会将数据刷出来。而系统调用不带缓冲区,所以直接输出到标准输出。

printf默认缓冲方式为行缓冲,但是当printf往显示器或标准输出上打印为航缓冲,若重定向到文件时,它的默认刷新方式变为全缓冲(初始时不刷新,直到满了再刷新)

*三种缓冲方式:无缓冲、行缓冲、全缓冲

1.fwrite等不是系统调用

2.系统调用和文件指针

3.缓冲方式

     3.vfork

     vfork用于创建一个新进程,该新进程的目的进程是exec一个新程序,vfork和fork都创建一个子进程,但它不将父进程的地址空间复制到子进程中,因为子进程会立即调用exec。在子进程调用exec和exit之前,它在父进程空间中运行,会更改父进程数据段。堆和栈。且vfork保证子进程先运行,在调用exec或exit之后父进程才可以被调度运行。

 1.父子进程数据段和代码段共享

 2.子进程先运行

例:

int g_value;

int main

{

    pid_ id =vfork();

    if(id<0)

    {

           printf("fork error,%s\n",streror(error));

    }

    else if(id==0)

    {

        g_value=200;

        printf("child:%d",pid)//子进程修改数据后,父进程数据被修改(共享数据段)

        sleep(5);

        exit();//先运行子进程,打印后休眠5秒退出后运行父进程//若改为return 0会每次打印多了两条消息

    }

    else

    {

           printf("father")

    }

}

线程-->当前进程的线程会在当前进程的地址空间运行,vfork和线程相当有关

本文出自 “无以伦比的暖阳” 博客,请务必保留此出处http://10797127.blog.51cto.com/10787127/1793059

子进程

标签:进程   子进程   文件描述符   

原文地址:http://10797127.blog.51cto.com/10787127/1793059

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!