1. 程式人生 > >linux系統編程:進程控制(fork)

linux系統編程:進程控制(fork)

bsp ec2 兩個 緩沖 argc 刷新 方式 進程 進程pid

在linux中,用fork來創建一個子進程,該函數有如下特點:

1)執行一次,返回2次,它在父進程中的返回值是子進程的 PID,在子進程中的返回值是 0。子進程想要獲得父進程的 PID 需要調用 getppid 函數。

2)生成的子進程會復制fork函數之後的代碼

3)父子進程的全局變量和局部變量,是不共享的

4)子進程會繼承父進程的環境狀態

/*================================================================
*   Copyright (C) 2018 . All rights reserved.
*   
*   文件名稱:fork.c
*   創 建 者:ghostwu(吳華)
*   創建日期:2018年01月12日
*   描    述:fork基本使用
*
================================================================
*/ #include <stdio.h> #include <stdlib.h> #include <unistd.h> int count = 10; int main(int argc, char *argv[]) { pid_t pid; int var = 5; printf( "----fork之前------,當前進程id=%d\n", getpid() ); pid = fork(); printf( "----fork之後------\n" );
if( pid < 0 ) { perror( "fork" ); exit( -1 ); }else if( pid == 0 ) { //子進程 var++; count++; }else { sleep( 3 ); } printf( "fork返回值pid=%d, 當前進程pid=%d, count=%d, var=%d\n", pid, getpid(), count, var ); return 0; }

技術分享圖片

上例,我們可以看出:

1)子進程並不會輸出"fork之前“這段代碼,因為子進程拷貝的是fork之後的代碼

2)子進程對變量操作之後,對父進程的變量沒有任何影響,他們是2個不同的副本

3)標準輸出是行緩沖模式:遇到換行符時進行刷新、緩沖區滿了的時候刷新、強制刷新(fflush);而標準輸出(stdout)是行緩沖,因為涉及到終端設備;

把這個例子的輸出方式,再改一下:

技術分享圖片

這裏,你會發現,多了兩個輸出( "fork之前" ),因為,采用管道重定向輸出之後,IO操作就變成了全緩沖模式,子進程產生的時候是會復制父進程的緩沖區的數據的,所以子進程刷新緩沖區的時候子進程也會將從父進程緩沖區中復制到的內容刷新出來。因此,在使用 fork產生子進程之前一定要使用 fflush(NULL) 刷新所有緩沖區!

技術分享圖片
/*================================================================
*   Copyright (C) 2018 . All rights reserved.
*   
*   文件名稱:fork.c
*   創 建 者:ghostwu(吳華)
*   創建日期:2018年01月12日
*   描    述:fork基本使用
*
================================================================*/


#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int count = 10;

int main(int argc, char *argv[])
{
    pid_t pid;    

    int var = 5;

    printf( "----fork之前------,當前進程id=%d\n", getpid() );


    fflush( NULL );
    pid = fork();

    printf( "----fork之後------\n" );

    if( pid < 0 ) {
        perror( "fork" );
        exit( -1 );
    }else if( pid == 0 ) { 
        //子進程
        var++;
        count++;
    }else {
        sleep( 3 );
    }

    printf( "fork返回值pid=%d, 當前進程pid=%d, count=%d, var=%d\n", pid, getpid(), count, var );
    return 0;
}
View Code

技術分享圖片

這個時候,就不會有兩個("fork之前" ),因為fork生成子進程之前,已經把父進程緩沖區的數據刷新到內核緩沖區,不在標準IO的緩沖區

子進程如果比父進程先結束,那麽子進程會變成僵屍進程。

因為:它們必須得等待父進程為其“收屍”才能徹底釋放,如果父進程先結束了,那麽這些子進程的父進程會變成 1 號 init 進程,當這些子進程運行結束時會變成僵屍進程,然後 1 號 init 進程就會及時為它們收屍

技術分享圖片
/*================================================================
*   Copyright (C) 2018 . All rights reserved.
*   
*   文件名稱:fork3.c
*   創 建 者:ghostwu(吳華)
*   創建日期:2018年01月12日
*   描    述:
*
================================================================*/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(int argc, char *argv[])
{
    pid_t pid;
    int i = 0;

    for( i = 0 ; i < 10; i++ ) {
        pid = fork();
        if( pid < 0 ) {
            perror( "fork()" );
            exit( -1 ); 
        }else if( pid == 0 ) {
            printf( "[pid]=%d\n", getpid() );
            exit( 0 );
        }
    }
    sleep( 10 );
    
    return 0;
}
View Code

技術分享圖片

父進程如果比子進程先結束,那麽子進程會變成孤兒進程

所有子進程的父進程都變成了 1 號 init 進程

技術分享圖片
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(int argc, char *argv[])
{
    pid_t pid;
    int i = 0;

    for( i = 0 ; i < 10; i++ ) {
        pid = fork();
        if( pid < 0 ) {
            perror( "fork()" );
            exit( -1 ); 
        }else if( pid == 0 ) {
            sleep( 10 );
            printf( "[pid]=%d\n", getpid() );
            exit( 0 );
        }
    }
    
    return 0;
}
View Code

技術分享圖片

linux系統編程:進程控制(fork)