前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >进程终止介绍

进程终止介绍

作者头像
Yui_
发布2024-10-16 08:58:31
690
发布2024-10-16 08:58:31
举报
文章被收录于专栏:Yui编程知识

在计算机系统中,进程是操作系统分配资源的基本单位,而进程终止则是因为则是因为操作系统由于某种原因结束一个进程的执行。这可能是因为进程完成了某种任务,也可能是因为出现了错误或异常。 创建一个进程的过程:先描述再组织。创建一个内核数据结构,在进行复杂代码和数据。那么终止一个进程的过程和创建一个进程的顺序是相反的,终止一个进程的本质就是:释放曾经的代码和数据所占的空间,释放内核数据结构。

1.利用echo查看进程退出情况

语法:

代码语言:javascript
复制
echo $?

功能:返回最近一个进程的退出情况。 现在我们来写段hello world的代码,来验证echo的功能。

代码语言:javascript
复制
#incldue <stdio.h>

int main()
{
	printf("hello world\n");
	return 0;
}
查看进程退出情况
查看进程退出情况

可以看到,echo返回的是0。那么这个所谓的0是进程正常退出,还是异常呢?

答案是正常退出,明明在C语言里,0表示假啊。是这样没错啦,但是你要考虑到,进程的退出虽然只有正常和异常之分,可异常退出的情况却存在的着很多种啊,我们需要利用数字来标记这些异常的情况,为此所以才会产生0表示正常退出,而非0的整数表示不同的异常退出。

写一个错误进程来看看吧,查看一个不存在的文件。

代码语言:javascript
复制
ls hahahaha
返回2
返回2

现在进程的退出码就不是0了,那肯定就说明了这个进程是异常退出的。那么我们怎么才能知道这些错误码所对应的错误信息呢? strerror就出现了,C语言用strerror存储了会遇见的所有出错信息。

2. strerror介绍

先来打印一下2对应什么错误信息吧。

代码语言:javascript
复制
#include <stdio.h>
#include <string.h>

int main()
{
	printf("%s",strerror(2));
	return 0;
}

//打印结果
//No such file or directory

和上面的出错信息差不多呢。 那么我们来看看到底有多少的错误信息吧:

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

从代码发现,一共有133个错误信息。

3.自定义退出码

我们可以通过枚举未自定义退出码进行赋值,将退出码设置为全局变量,在每个函数的每一种结果中都需要将退出码进行修改,再通过接受退出码的值翻译为错误信息的字符串。

代码语言:javascript
复制
#include <stdio.h>

enum{
    SUCCESS = 0,
    DIV_ZERO,
    MOD_ZERO,
};

int errcode = SUCCESS;

int div_cal(int a,int b)
{
    if(b == 0){
        errcode = DIV_ZERO;
        return -1;
    }
    else{
        return a/b;
    }
}
//翻译错误码
char* traErr(int error)
{
    switch(error)
    {
        case SUCCESS:
            return "SUCCESS";
        case DIV_ZERO:
            return "DIV_ZERO";
        case MOD_ZERO:
            return "MOD_ZERO";
        default:
            return NULL;
    }
}

int main()
{
    int ans = div_cal(10,2);
    printf("answer: %d Error:%s\n",ans,traErr(errcode));
    int ans2 = div_cal(10,0);
    printf("answer:%d Error:%s\n",ans2,traErr(errcode));

    return 0;
}
代码语言:javascript
复制
打印结果:
answer: 5 Error:SUCCESS
answer:-1 Error:DIV_ZERO

4. 进程终止

4.1 进程退出的场景

  • 代码运行完毕,结果正确。
  • 代码运行完毕,结果不正确。
  • 代码异常终止。

4.2 进程常见的退出方法

正常退出:

  1. 从main返回。
  2. 调用exit。
  3. \_exit 异常退出:

ctrl + c,信号终止。

当进程死循环时,除了使用ctrl+c外,还可以使用kill -9 pid来杀死进程。

代码语言:javascript
复制
#include <stdio.h>
#include <unistd.h>

int main()
{
    while(1){
        printf("i am a process,pid = %d\n",getpid());
        sleep(1);
    }
    return 0;
}
kill 进程
kill 进程

4.3 exit函数和_exit函数

_exit 函数参数:status定义进程的终止状态,父进程通过wait来获取该值。 说明:虽然status是int类型,但是仅仅有8位可以被父进程使用,所以_exit(-1)时,在终端执行echo $?会发现返回值是255。这里运用到的是状态压缩。 exit eixt函数最后会调用_exit函数,但是在调用前还会做一些其他操作。

  • 执行用户通过atexit或者on_exit定义的清理函数。
  • 关闭所有打开的流,所有的缓存数据均被刷新。
  • 调用_exit。 验证第二点
  • 代码调用exit函数,在进程退出后,会刷新缓冲区。
  • 系统调用_exit函数,在进程退出后,不会刷新缓冲区。
代码语言:javascript
复制
#include <stdio.h>
#include <stdlib.h>
int main()
{
    printf("hahah"); //注意不要写\n,使用\n会直接刷新数据
    exit(1);
    return 0;
}
代码语言:javascript
复制
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
    printf("hahah");
    _exit(1);
    return 0;
}

mybin2为调用exit函数的可执行文件 mybin3为_调用exit函数的可执行文件

缓冲区
缓冲区

我的博客即将同步至腾讯云开发者社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=2wnen263eb6sk

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-10-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.利用echo查看进程退出情况
  • 2. strerror介绍
  • 3.自定义退出码
  • 4. 进程终止
    • 4.1 进程退出的场景
      • 4.2 进程常见的退出方法
        • 4.3 exit函数和_exit函数
        相关产品与服务
        云开发 CloudBase
        云开发(Tencent CloudBase,TCB)是腾讯云提供的云原生一体化开发环境和工具平台,为200万+企业和开发者提供高可用、自动弹性扩缩的后端云服务,可用于云端一体化开发多种端应用(小程序、公众号、Web 应用等),避免了应用开发过程中繁琐的服务器搭建及运维,开发者可以专注于业务逻辑的实现,开发门槛更低,效率更高。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档