int main(int argc,char *argv[])进程的终止情况
正常终止:
从main函数返回
调用exit
调用_exit或_Exit
最后一个线程从其启动例程返回
异常终止:
调用abort
接到一个信号并终止
最后一个线程对其取消请求做出响应
echo $?//打印上一条语句的执行状态
#include#include int main() { printf("hellon"); return 0; }
echo $?显示的是0
相关函数:
exit
------------------ cause normal process termination
#includevoid exit(int status);
描述:
The exit() function causes normal process termination and the value of status & 0377 is returned to the parent (see wait(2)). All functions registered with atexit(3) and on_exit(3) are called, in the reverse order of their registration.
atexit//钩子函数//类似C++里的析构函数
---------------------- register a function to be called at normal process termination
注册一个函数,这个函数将会被调用,在进程正常终止的时候
#includeint atexit(void (*function)(void));
例子:
#include#include static void f1(void) { puts("f1() is working!"); } static void f2(void) { puts("f2() is working!"); } static void f3(void) { puts("f3() is working!"); } int main() { puts("Begin!"); atexit(f1); atexit(f2); atexit(f3); puts("End!"); exit(0); }
运行结果:
解说:先打印Begin然后将函数挂在钩子上,在打印End,在函数结束前,最后逆序调用
伪码表示钩子函数的作用:
fd1=open();
if(fd1<0)
{
perror();
exit(1);
}
fd2=open();
if(fd2<0)
{
close(fd1);
perror();
exit(1);
}
…
fd100=open();
if(fd100<0)
{
close(fd1);
close(fd2);
close(fd3);
…
close(fd99);//这样子的不是我们想要的
perror();
exit(1);
}
改善方法,加上钩子函数就好
fd1=open();
if(fd1<0)
{
perror();
exit(1);
}
fd2=open();
atexit();----->close(fd1);
if(fd2<0)
{
perror();
exit(1);
}
atexit();----->close(fd2);
…
fd100=open();
if(fd100<0)
{
perror();
exit(1);
}
atexit();----->close(fd100);
_exit, _Exit //系统调用,exit依赖于它们
----------------- terminate the calling process
#includevoid _exit(int status); #include void _Exit(int status);
伪代码分析exit和_exit的区别:
int func()
{
return 0/1/2;
}
int main()
{
int f;
f=func();,
…
switch(f)
{
case 0:
case 1:
case 2:
default:
}
}
如果运行到default那么我们可以怀疑,在f=func出现了问题,很有可能是写越界。如果这个时候exit,那么就会调用各种钩子函数,io刷新,该同步的同步,该刷新的刷新。这很有可能导致故障扩大。这个时候我们最好调用_exit,直接退出。或是利用abort();
getopt();
getopt_long();//分析长格式
#include
int getopt(int argc, char * const argv[], const char *optstring);
extern char *optarg;//当分析命令行上串的时候,如果看到摸一个选项加了冒号,那么拿到这个选项的时候,optarg指针默认指向后面修饰的那个串
extern int optind//表示当前读到的argv的下标, opterr, optopt;
int getopt_long(int argc, char * const argv[],
const char *optstring,
const struct option *longopts, int *longindex);
If the first character of optstring is ‘-’, then each nonoption argv-element is handled as if it were the argument of an option with character code 1 //“-“识别非选项的传参
如果串的第一个字符是”-”,那么遇到每一个非选项参数的时候就会返回1,当我们拿到了这个非选项传参,就会返回1,返回1以后,optind指针就会指向下一个argv
例子:
实现./mydate -y得到年份 -m得到月份等等
对于年份是想要两位的还是四位的,对于小时是想要24小时制的还是12小时制的
如果在终端有文件名,则将内容输出到这个文件上否则就输出到终端
#include#include #include #include #include #define FMTSTRSIZE 1024 #define TIMESTRSIZE 1024 int main(int argc,char *argv[]) { FILE * fp=stdout; time_t stamp; char fmtstr[FMTSTRSIZE]; struct tm *tm; char timestr[TIMESTRSIZE]; int c; fmtstr[0]=' '; stamp=time(NULL); tm=localtime(&stamp); while(1) { c=getopt(argc,argv,"-H:MSy:md"); if(c<0) { break; } switch(c) { case 1: fp=fopen(argv[optind-1],"w"); if(fp==NULL) { perror("fopen()"); fp=stdout; } break; case 'H': if(strcmp(optarg,"12")==0) { strncat(fmtstr,"%I(%P) ",FMTSTRSIZE); } else if(strcmp(optarg,"24")==0) { strncat(fmtstr,"%H",FMTSTRSIZE); } else fprintf(stderr,"invalid argument"); break; case 'M': strncat(fmtstr,"%M ",FMTSTRSIZE); break; case 'S': strncat(fmtstr,"%S ",FMTSTRSIZE); break; case 'y': if(strcmp(optarg,"2")==0) { strncat(fmtstr,"%y ",FMTSTRSIZE); } else if(strcmp(optarg,"4")==0) { strncat(fmtstr,"%Y ",FMTSTRSIZE); } else fprintf(stderr,"invlid argument"); break; case 'm': strncat(fmtstr,"%m ",FMTSTRSIZE); break; case 'd': strncat(fmtstr,"%d ",FMTSTRSIZE); break; default: break; } } strncat(fmtstr,"n",FMTSTRSIZE); strftime(timestr,TIMESTRSIZE,fmtstr,tm); fputs(timestr,fp); if(fp!=stdout) { fclose(fp); } exit(0); }



