总结了Linux中经常用到的sleep和exit函数
涉及
sleep
kill命令
exit _exit _Exit
atexit
tmpfile
abort
setjmp longjmp
exit部分是转载内容

1. Linux sleep库函数

#include <unistd.h>

使调用sleep函数的线程休眠seconds秒如果中间有一个未被忽略的信号到达则终止休眠,如果该程序没有终止(比如对于某个信号定义了信号处理程序)从sleep函数后面的语句继续执行。

返回剩余的休眠秒数。即如果请求的休眠时间已经过去则返回0,如果中途被信号处理程序中断则返回剩余的休眠秒数

unsigned int sleep(unsigned int seconds);

示例:用一个信号唤醒一个进程的休眠

test4.c

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <signal.h>
//信号处理函数
void sigFunc(int sig){printf("catch signal 14\n");
}
int main(){int seconds = 20;signal(SIGALRM ,sigFunc);  //注册SIGALRM信号的信号处理函数printf("this proceed pid is %d\n",getpid());printf("begin sleep %d seconds\n",seconds);int lastTime = sleep(seconds);  //调用线程休眠seconds秒并返回剩余休眠时间printf("stop sleeping, last %d seconds\n",lastTime);
}

运行结果:在一个终端编译并运行以上程序,看出该进程pid为3834。

然后另开另一个进程输入 kill -14 3834向3834进程发送信号14。可以看出该信号被进程处理函数成功捕获,sleep被终止并返回剩余休眠时间

xtark@xtark-vmpc:~/桌面/linux_study/section8$ gcc test4.c
xtark@xtark-vmpc:~/桌面/linux_study/section8$ ./a.out
this proceed pid is 3834
begin sleep 20 seconds
catch signal 14
stop sleeping, last 4 seconds

补充:Linux中的kill命令

可以通过kill -l查看所有信号

xtark@xtark-vmpc:~$ kill -l1) SIGHUP     2) SIGINT   3) SIGQUIT  4) SIGILL   5) SIGTRAP6) SIGABRT    7) SIGBUS   8) SIGFPE   9) SIGKILL 10) SIGUSR1
11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM
16) SIGSTKFLT   17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP
21) SIGTTIN 22) SIGTTOU 23) SIGURG  24) SIGXCPU 25) SIGXFSZ
26) SIGVTALRM   27) SIGPROF 28) SIGWINCH    29) SIGIO   30) SIGPWR
31) SIGSYS  34) SIGRTMIN    35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3
38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8
43) SIGRTMIN+9 44) SIGRTMIN+10    45) SIGRTMIN+11    46) SIGRTMIN+12    47) SIGRTMIN+13
48) SIGRTMIN+14    49) SIGRTMIN+15    50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12
53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9  56) SIGRTMAX-8  57) SIGRTMAX-7
58) SIGRTMAX-6  59) SIGRTMAX-5  60) SIGRTMAX-4  61) SIGRTMAX-3  62) SIGRTMAX-2
63) SIGRTMAX-1  64) SIGRTMAX

通过kill -信号 进程pid 来给指定在进程发送指定信号

kill -14 3834      #向3834进程发送信号14
kill -SIGALRM 3834 #向3834进程发送信号14

通过kill 进程pid 来终止指定进程。

这个命令其实是向指定进程发送信号15即SIGTERM,但是TERM信号可以杀死不能捕获该信号的进程,而对于能捕获该信号的进程则可能无法杀死针对这些能捕获TERM信号的进程,可能需要信号9即SIGKILL才能终止进程,因为该信号不能够被俘获

kill 3834    #终止3834号进程

2. exit系统调用与库函数

exit终止调用进程

2.1 exit系统调用

Linux中exit系统调用函数即为_exit()_Exit()

_exit() 函数立即终止调用进程。 属于该进程的任何打开的文件描述符fd都将关闭; 该进程的任何子进程都由进程 1即init进程继承,并且该进程的父进程被发送一个 SIGCHLD 信号17

SIGCHLD信号:在一个进程终止或者停止时,将SIGCHLD信号发送给其父进程,按系统默认将忽略此信号,如果父进程希望被告知其子系统的这种状态,则应捕捉此信号。该信号的捕捉函数中通常调用wait系统调用以取得子进程pid和其终止状态

status值作为进程的退出状态返回给父进程,并且可以使用 wait系列系统调用获取到该子进程的退出状态与pid。

函数_Exit() 等价于_exit()

#include <unistd.h>
void _exit(int status);
#include <stdlib.h>
void _Exit(int status);

2.2 exit库函数

立即终止调用进程。任何属于该进程的打开的文件描述符都会被关闭,该进程的子进程由进程 1 继承,且会向父进程发送一个 SIGCHLD 信号(这些步骤其实是exit函数内部发出_exit系统调用来完成的)。

参数是程序退出时的状态码,0表示正常退出,其他表示非正常退出,一般都用-1或者1,建议用标准C中的宏EXIT_SUCCESSEXIT_FAILUREexit(EXIT_SUCCESS);

#include <stdlib.h>
void exit(int status)

2.3 _exit系统调用和exit库函数区别

此部分转载自该网址
_exit()函数的作用最为简单:直接使进程停止运行,清除其使用的内存空间,并销毁其在内核中的各种数据结构。exit() 函数则在这些基础上作了一些包装,在执行退出之前加了若干道工序。
exit()库函数与_exit()系统调用最大的区别就在于exit()函数在调用exit系统调用之前要检查文件的打开情况,把文件缓冲区中的内容写入文件,即”清理I/O缓冲”

exit()在结束调用它的进程之前,要进行如下步骤:

  1. 调用atexit()注册的函数(出口函数)。按atexit注册时相反的顺序调用所有由它注册的函数,这使得我们可以指定在程序终止时执行自己的清理动作。例如,保存程序状态信息于某个文件,解开对共享数据库上的锁等。
  2. 清理I/O缓冲(刷新所有打开的输出流,即把文件缓冲区中的内容写入文件),删除用tmpfile函数建立的所有临时文件.
  3. 最后调用_exit()函数终止进程

_exit()系统调用做以下事:

  1. 关闭该进程打开的文件描述符
  2. 该进程的任何子进程都由进程1继承
  3. 向该进程的父节点发送SIGCHLD信号

补充atexit库函数

当程序正常终止时,调用指定的函数 func。可以在任何地方注册终止函数,但它会在程序终止(exit函数而不能是_exit系统调用)的时候被调用(按注册时的相反顺序调用)。

#include <stdlib.h>
int atexit(void (*func)(void));

示例:

#include <stdio.h>
#include <stdlib.h>
void func1(){puts("func 1");
}
void func2(){puts("func 2");
}
void func3(){puts("func 3");
}
int main(){atexit(func1);atexit(func2);atexit(func3);
}

运行结果:可见进程终止时按照atexit注册的相反顺序调用函数

xtark@xtark-vmpc:~/桌面/linux_study/section8$ gcc test5.c
xtark@xtark-vmpc:~/桌面/linux_study/section8$ ./a.out
func 3
func 2
func 1

补充:tmpfile库函数

以二进制更新模式(wb+)创建临时文件。被创建的临时文件会在流关闭的时候(调用fclose函数关闭临时文件)或者在程序终止的时候自动删除

如果成功,该函数返回一个指向被创建的临时文件的流指针。如果文件未被创建,则返回 NULL。

#include <stdio.h>
FILE *tmpfile(void);

示例:操作临时文件。

#include <stdio.h>
#include <stdlib.h>int main(){FILE* f = tmpfile();   //创建临时文件并以"wb+"模式打开const char * str = "123 demaxiya";fputs(str,f);    //向临时文件写入数据/*移动文件读写指针到开头,这一步必须,否则读写指针在文件末尾读取不到数据*/rewind(f);  int c;while((c = fgetc(f)) != EOF){ //从临时文件读取字符直到文件末尾printf("%c",c);}printf("\n");
}

运行结果:成功完成了临时文件读写基本操作

xtark@xtark-vmpc:~/桌面/linux_study/section8$ gcc test5.c
xtark@xtark-vmpc:~/桌面/linux_study/section8$ ./a.out
123 demaxiya

3. abort库函数

异常终止一个进程,直接从调用的地方跳出

#include <stdlib.h>
void abort(void);

abort()首先解除了对SIGABRT(6)信号的阻止,然后为调用进程发送该信号(就像调用了 raise(SIGABRT)一样)。 导致进程的非正常终止,除非SIGABRT 信号被捕获,并且信号处理函数没有返回(使用了longjmp库函数使信号处理函数没有返回)。

如果abort()函数导致进程终止,则关闭和刷新所有打开的文件流

需要注意如果SIGABRT信号被忽略,或者被一个信号处理函数捕获。abort()函数仍然会终止进程。

4. 补充setjmplongjmp

非局部跳转语句。

可以通过setjmp与longjmp完成程序跳转,会造成函数不返回。与goto语句不同,goto只能在函数内跳转,而setjmp和longjmp可以在不同函数之间跳转,在栈上跳过若干调用帧,返回到当前函数调用路径上的某一个函数中。

4.1 setjmp宏

初始化jmp_buf缓冲区,用于将来跳转回此处(设置返回点)。保存程序的调用环境于env参数所指的缓冲区(保存调用函数的栈环境于env中),env将被longjmp使用。如果是从setjmp直接调用返回,setjmp返回值为0。如果是从longjmp恢复的程序调用环境返回,setjmp返回非零值

#include <setjmp.h>
int setjmp(jmp_buf env)
#define setjmp(env) _setjmp (env) // setjmp宏定义
  • 参数:参数env是一个jmp_buf类型变量,该类型用于存储环境信息

  • 返回值:这个宏可能不只返回一次。第一次,在直接调用它时返回0。当调用 longjmp 时带有设置的环境信息,这个宏会再次返回,此时它返回的值是 longjmp 的第二个参数。

4.2 longjmp库函数

恢复最近一次调用 setjmp() 宏时保存的环境(跳回setjmp处,相当于恢复现场

void longjmp(jmp_buf environment, int value)
  • 参数environment:类型为 jmp_buf 的对象,包含了调用 setjmp 时存储的环境信息
  • 参数value:setjmp 宏第二次返回值

4.3 使用示例:

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <signal.h>
#include <setjmp.h>
#include <stdlib.h>
jmp_buf env;  //jmp_buf类型变量,该类型用于存储环境信息
void func(){printf("进入func函数\n");longjmp(env,3);  //跳转到setjmp处,造成func函数不返回printf("不会执行到这里1\n");
}int main(){int num = 0;if(!(num = setjmp(env))){func();printf("不会执行到这里2\n");}else{printf("setjmp返回 %d\n",num);}
}

运行结果:可见部分代码跳过了,func函数由于longjmp导致没有返回

xtark@xtark-vmpc:~/桌面/linux_study/section8$ gcc test6.c
xtark@xtark-vmpc:~/桌面/linux_study/section8$ ./a.out
进入func函数
setjmp返回 3

需要注意,longjmp必须在setjmp的作用域之内

在一个函数中使用setjmp来初始化一个jmp_buf,只要该函数未曾返回,那么在其它任何地方都可以通过longjmp调用来跳转到 setjmp的下一条语句执行。但是如果该函数返回了,局部内存就失效了(栈内存回收了),因此从其他地方通过longjmp调用来跳回setjmp并使用局部变量会导致出错

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <signal.h>
#include <setjmp.h>
#include <stdlib.h>
jmp_buf env;
void funcB(){longjmp(env,3);
}
void funcA(){int a = 1;setjmp(env);printf("%d\n",a);//使用局部变量
}int main(){funcA();funcB();
}

运行结果:由于funcA函数返回造成栈内存回收,通过longjmp跳转回setjmp并使用局部变量会出错

xtark@xtark-vmpc:~/桌面/linux_study/section8$ gcc test6.c
xtark@xtark-vmpc:~/桌面/linux_study/section8$ ./a.out
1
0

5. C++中的terminate函数

void terminate();
C++中,异常不可以忽略,当异常找不到匹配的catch字句时,会调用系统的库函数terminate(),默认情况下,terminate()函数调用标准C库函数abort()使程序终止而退出。

Linux sleep exit abort函数相关推荐

  1. Linux SIGABRT和abort()函数

    SIGABRT被阻塞 还有一个信号SIGABRT要特别说明,表示异常终止信号,当系统调用abort()时会发送SIGABRT信号,那么如果阻塞了该信号会影响abort()函数的使用吗? 经过测试,事实 ...

  2. 【Linux 内核】进程管理 ( 进程状态 | 进程创建 | 进程终止 | 调用 exit 系统调用函数主动退出 | main 函数返回自动退出 | kill 杀死进程 | 执行异常退出 )

    文章目录 一.进程状态 二.进程创建 三.进程终止 ( 调用 exit 系统调用函数主动退出 | main 函数返回自动退出 | kill 杀死进程 | 执行异常退出 ) 一.进程状态 Linux 进 ...

  3. linux中进程退出函数:exit()和_exit()的区别

    linux中进程退出函数:exit()和_exit()的区别 (1)_exit()执行后立即返回给内核,而exit()要先执行一些清除操作,然后将控制权交给内核. (2)调用_exit函数时,其会关闭 ...

  4. Linux下Exit和_exit函数说明

    exit和_exit函数都是用来终止进程的.当程序执行到exit或_exit时,系统无条件的停止剩下所有操作,清除包括PCB(进程控制块)在内的各种数据结构,并终止本进程的运行.但是,这两个函数是有区 ...

  5. abort函数和exit函数

    函数名: abort 功 能: 异常终止一个进程 用 法: void abort(void); 头文件:#include <stdlib.h> 说明:abort函数是一个比较严重的函数,当 ...

  6. linux的基础知识——raise函数,abort函数和定时函数

    1.raise和abort函数 \qquadraise函数:int raise(int sig) \qquad功能:给当前进程发送指定信号(自己给自己发信号),raise(signo)相当于kill( ...

  7. linux c语言内核函数手册,Linux C函数实例速查手册

    函数学习目录: 第1章 初级I/O函数 1.1 close函数:关闭已经打开的文件 1.2 creat函数:创建一个文件 1.3 dup函数:复制文件描述符 1.4 dup2函数:复制文件描述符到指定 ...

  8. exit abort return 区别

    exit(): 在调用时,会做大部分清理工作,但是决不会销毁局部对象,因为没有stack unwinding. 会进行的清理工作包括:销毁所有static和global对象,清空所有缓冲区,关闭所有I ...

  9. Linux可重入函数

    1.可重入函数 可重入函数指的是可以被中断的函数.也就是说,可以在这个函数执行的任何时刻中断它,转入OS调度下去执行另外一段代码,而返回控制时不会出现什么错误:而不可重入的函数由于使用了一些系统资源, ...

  10. linux C语言perror()函数(将错误消息写入标准错误)(把一个描述性错误消息输出到标准错误 stderr。首先输出自定义字符串 str,后跟一个冒号,然后是一个空格)

    文章目录 man 3 perror man 3posix perror 20220723 C语言 | perror函数使用详解 man 3 perror PERROR(3) Linux Program ...

最新文章

  1. 《SharePoint Portal Server 2003 深入指南》出版预告
  2. jQuery实现自动左右滚动效果的代码实例
  3. 判断一个字符串是另外字符串的旋转字符串
  4. DELL台式机BIOS常见问题
  5. ps cs3中显示任何像素不大于50%选择。选区边将不可见是什么意思
  6. matlab光盘映像文件可以删除吗_DVD-Cloner 2020 for mac(DVD光盘刻录工具) 7.00.715
  7. P4294-[WC2008]游览计划【斯坦纳树】
  8. redis——HyperLogLog
  9. 中国工程院院士徐宗本:大数据的挑战和问题
  10. log analysis Werzeug aus Deutschland Dr
  11. C语言:求两个整数的最大公约数
  12. 多台或者集群环境下如何保证spring定时器只执行一个
  13. 读书笔记——思维导图带你看《哲学起步》
  14. MAPREDUCE原理篇(1)
  15. 环境判断:区别h5打开还是weixin打开?
  16. 如何写Java单元测试
  17. 艾永亮:只要改变这两点,传统健身房行业可以逃离浩沙死咒
  18. 【windows查看电脑属性配置 dxdiag】
  19. vscode中切换远程分支
  20. 8000字解读安踏理想汽车丨打破用户体验黑箱的实战策略

热门文章

  1. C# 地理信息系统GIS开源软件
  2. 如何下载最新的NDVI数据?需要翻墙,安装MRT,如何处理下载的NDVI数据?
  3. 区块链技术可简化房地产交易流程
  4. 了解交换机、路由器、网关的概念以及它们各自属于什么层次?
  5. mac datagrip如何建立本地链接
  6. 华为交换机配置syslog发送_华为交换机的 syslog功能
  7. 这一刻我學會了堅強、給我一雙翅膀,我会向天空去翱翔。
  8. 青光眼 程序员_青光眼-如何不失明:让我们谈谈治疗方法…
  9. MATLAB小技巧(30)非线性拟合 lsqcurefit
  10. 洛谷—— P1419 寻找段落