进程控制1(进程创建,进程终止)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/liu_zhen_kai/article/details/81839786

进程创建

fork()与vfork()

  • fork()
//man手册
pid_t fork(void);
fork()  creates a new process by duplicating the calling process.  The new process, referred
       to as the child, is an exact duplicate of the calling process

创建一个子进程,子进程完全拥有父进程的资源,但是fork的字符进程有自己的独立空间,也就是当子进程在进行写入等数据改变的时候,操作系统会分派新的空间。

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 
  4 int _val = 100;
  5 
  6 int main(void)
  7 {
  8     pid_t pid = fork();
  9 
 10     if(pid < 0)
 11         perror("fork : "),
 12             exit(0);
 13     else if(pid == 0)
 14     {
 15         _val = 200;
 16         printf("this is child _val  : %d and it's addr : %p\n", _val, &_val);
 17     }
 18     else
 19     {
 20         printf("this is parent _val  : %d and it's addr : %p\n", _val, &_val);
 21     }
 22 
 23     return 0;
 24 }

运行结果

[liu@localhost fork_vfork]$ ./fork 
this is parent _val  : 100 and it's addr : 0x80497b4
this is child _val  : 200 and it's addr : 0x80497b4

即使在子进程改变数据,也不能影响到父进程中的代码数据,因为二者是独立的(写时拷贝)

  • vfork()
//man手册
(From POSIX.1) The vfork() function has the same effect as fork(2), except that the behavior
       is undefined if the process created by vfork() either modifies any data other than  a  vari-
       able of type pid_t used to store the return value from vfork(), or returns from the function
       in which vfork() was called,  or  calls  any  other  function  before  successfully  calling
       _exit(2) or one of the exec(3) family of functions.

创建一个子进程,但是在子进程写入的时候不会开辟新的物理内存空间,也就像浅拷贝,子进程与父进程共享内存空间。

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>


int _val = 100;

int main(void)
{
    pid_t pid = vfork();

    if(pid < 0)
    {
        perror("vfork : "),
            exit(0);
    }
    else if(pid == 0)
    {
        _val = 200;
        printf("this is child _val  : %d\n", _val);
        exit(0);
    }
    else
    {
        printf("this is parent _val  : %d\n", _val);
    }


    return 0;
}

运行结果

[liu@localhost fork_vfork]$ ./vfork 
this is child _val  : 200
this is parent _val  : 200

结果证明vfork创建的子进程在改变了变量之后父进程的资源也被改变了,所以vfork创建的子进程是一种“浅拷贝”。


进程终止

进程的退出场景

  • 代码运行完毕,结果正确
  • 代码运行完毕,结果错误
  • 代码异常中断

进程正常退出的退出方法:

  • 调用exit
  • 调用_exit
  • main函数调用return

退出码查询

echo $?
[liu@localhost fork_vfork]$ ls
fork  fork.c  vfork  vfork.c
[liu@localhost fork_vfork]$ echo $?
0

错误码

在echo $?查看返回码的过程中,每个返回码都代表着不同的信息:

  • 错误码的信息在 errno 中 The <errno.h> header file defines the integer variable errno, which is set by system calls
    and some library functions in the event of an error to indicate what went wrong. Its value
    is significant only when the return value of the call indicated an error (i.e., -1 from most
    system calls; -1 or NULL from most library functions); a function that succeeds is allowed
    to change errno.

  • 错误码可以被strerror函数转化成字符串信息The strerror() function returns a pointer to a string that describes the error code passed
    in the argument errnum, possibly using the LC_MESSAGES part of the current locale to select
    the appropriate language. This string must not be modified by the application, but may be
    modified by a subsequent call to perror(3) or strerror(). No library function will modify
    this string.

//来看看每个错误码代表信息
  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <errno.h>
  4 #include <string.h>
  5 
  6 int main(void)
  7 {
  8     int i = 0;
  9 
 10     for(;i < 133;++i){
 11         printf("errno [%-3d] : %s\n", i, strerror(i));
 12     }
 13 
 14     return 0;
 15 }

[liu@localhost fork_vfork]$ ./err 
errno [0  ] : Success
errno [1  ] : Operation not permitted
errno [2  ] : No such file or directory
errno [3  ] : No such process
errno [4  ] : Interrupted system call
errno [5  ] : Input/output error
errno [6  ] : No such device or address
errno [7  ] : Argument list too long
errno [8  ] : Exec format error
errno [9  ] : Bad file descriptor
errno [10 ] : No child processes
errno [11 ] : Resource temporarily unavailable
errno [12 ] : Cannot allocate memory
errno [13 ] : Permission denied
errno [14 ] : Bad address
errno [15 ] : Block device required
errno [16 ] : Device or resource busy
errno [17 ] : File exists
errno [18 ] : Invalid cross-device link
errno [19 ] : No such device
errno [20 ] : Not a directory
errno [21 ] : Is a directory
errno [22 ] : Invalid argument
errno [23 ] : Too many open files in system
errno [24 ] : Too many open files
errno [25 ] : Inappropriate ioctl for device
errno [26 ] : Text file busy
errno [27 ] : File too large
errno [28 ] : No space left on device
errno [29 ] : Illegal seek
errno [30 ] : Read-only file system
errno [31 ] : Too many links
errno [32 ] : Broken pipe
errno [33 ] : Numerical argument out of domain
errno [34 ] : Numerical result out of range
errno [35 ] : Resource deadlock avoided
errno [36 ] : File name too long
errno [37 ] : No locks available
errno [38 ] : Function not implemented
errno [39 ] : Directory not empty
errno [40 ] : Too many levels of symbolic links
errno [41 ] : Unknown error 41
errno [42 ] : No message of desired type
errno [43 ] : Identifier removed
errno [44 ] : Channel number out of range
errno [45 ] : Level 2 not synchronized
errno [46 ] : Level 3 halted
errno [47 ] : Level 3 reset
errno [48 ] : Link number out of range
errno [49 ] : Protocol driver not attached
errno [50 ] : No CSI structure available
errno [51 ] : Level 2 halted
errno [52 ] : Invalid exchange
errno [53 ] : Invalid request descriptor
errno [54 ] : Exchange full
errno [55 ] : No anode
errno [56 ] : Invalid request code
errno [57 ] : Invalid slot
errno [58 ] : Unknown error 58
errno [59 ] : Bad font file format
errno [60 ] : Device not a stream
errno [61 ] : No data available
errno [62 ] : Timer expired
errno [63 ] : Out of streams resources
errno [64 ] : Machine is not on the network
errno [65 ] : Package not installed
errno [66 ] : Object is remote
errno [67 ] : Link has been severed
errno [68 ] : Advertise error
errno [69 ] : Srmount error
errno [70 ] : Communication error on send
errno [71 ] : Protocol error
errno [72 ] : Multihop attempted
errno [73 ] : RFS specific error
errno [74 ] : Bad message
errno [75 ] : Value too large for defined data type
errno [76 ] : Name not unique on network
errno [77 ] : File descriptor in bad state
errno [78 ] : Remote address changed
errno [79 ] : Can not access a needed shared library
errno [80 ] : Accessing a corrupted shared library
errno [81 ] : .lib section in a.out corrupted
errno [82 ] : Attempting to link in too many shared libraries
errno [83 ] : Cannot exec a shared library directly
errno [84 ] : Invalid or incomplete multibyte or wide character
errno [85 ] : Interrupted system call should be restarted
errno [86 ] : Streams pipe error
errno [87 ] : Too many users
errno [88 ] : Socket operation on non-socket
errno [89 ] : Destination address required
errno [90 ] : Message too long
errno [91 ] : Protocol wrong type for socket
errno [92 ] : Protocol not available
errno [93 ] : Protocol not supported
errno [94 ] : Socket type not supported
errno [95 ] : Operation not supported
errno [96 ] : Protocol family not supported
errno [97 ] : Address family not supported by protocol
errno [98 ] : Address already in use
errno [99 ] : Cannot assign requested address
errno [100] : Network is down
errno [101] : Network is unreachable
errno [102] : Network dropped connection on reset
errno [103] : Software caused connection abort
errno [104] : Connection reset by peer
errno [105] : No buffer space available
errno [106] : Transport endpoint is already connected
errno [107] : Transport endpoint is not connected
errno [108] : Cannot send after transport endpoint shutdown
errno [109] : Too many references: cannot splice
errno [110] : Connection timed out
errno [111] : Connection refused
errno [112] : Host is down
errno [113] : No route to host
errno [114] : Operation already in progress
errno [115] : Operation now in progress
errno [116] : Stale file handle
errno [117] : Structure needs cleaning
errno [118] : Not a XENIX named type file
errno [119] : No XENIX semaphores available
errno [120] : Is a named type file
errno [121] : Remote I/O error
errno [122] : Disk quota exceeded
errno [123] : No medium found
errno [124] : Wrong medium type
errno [125] : Operation canceled
errno [126] : Required key not available
errno [127] : Key has expired
errno [128] : Key has been revoked
errno [129] : Key was rejected by service
errno [130] : Owner died
errno [131] : State not recoverable
errno [132] : Operation not possible due to RF-kill

exit ,_exit 和 return

  • exit() 被认为是温和型退出进程,在进程的任意地方调用都会使得进程退出,在退出的过程中会做 执行用户定义的清理函数,冲刷缓冲区,关闭流等的操作。
  • _exit被认为是强制退出进程,在任意地方调用,直接退出,不做任何清理工作
  • return仅仅是在main函数中才退出进程

关于exit与_exit之间的区别的代码例子:

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

int main(void)
{
    printf("hello");
    exit(0);
}
结果 
[liu@localhost fork_vfork]$ ./exit 
hello[liu@localhost fork_vfork]$

在进程结束之前做了清理工作,刷新缓冲区所以才将hello显示出来

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

int main(void)
{
    printf("hello");
    _exit(0);
}
[liu@localhost fork_vfork]$ ./_exit 
[liu@localhost fork_vfork]$ 

_exit()没有刷新缓冲区,进程直接退出

其实exit与main函数的return 在底层的实现是调用了_exit

图解exit和_exit

exit和_exit

猜你喜欢

转载自blog.csdn.net/liu_zhen_kai/article/details/81839786