1.main 函数
c程序总是从main函数开始执行,当内核执行c程序时,在调用main前先调用一个特殊的启动例程,启动例程从内核获得命令行参数和环境变量值,然后为按上述方式调用main做好安排
2.进程终止
有8种方式使进程终止:
1)从main返回
2)调用exit
3)调用_exit或_Exit
4)最后一个线程从其启动例程返回
5)最后一个线程调用pthread_exit
6)调用abort
7)接到一个信号并终止
8)最后一个线程对取消请求做出相应
有三个函数用来正常终止一个程序
#include <stdlib.h> void exit(int status); void _Exit(int status); #include <unistd.h> void _exit(int status);
_exit和_EXit立即进入内核,exit则先执行一些清理处理。
atexit函数用来登记终止处理程序
#include <stdlib.h>
int atexit(void (*func)(void));
例:
#include "apue.h" static void my_exit1(void); static void my_exit2(void); int main(void) { if (atexit(my_exit2) != 0) err_sys("can't register my_exit2"); if (atexit(my_exit1) != 0) err_sys("can't register my_exit1"); if (atexit(my_exit1) != 0) err_sys("can't register my_exit1"); printf("main is done\n"); return(0); } static void my_exit1(void) { printf("first exit handler\n"); } static void my_exit2(void) { printf("second exit handler\n"); }
3.命令行参数(略)
4.环境表
5.c程序的存储空间
6.共享库
7.存储器分配
#include <stdlib.h> void *malloc(size_t size); void *calloc(size_t nobj, size_t size); void *realloc(void *ptr, size_t newsize);
|
All three return: non-null pointer if OK, NULL on error |
void free(void *ptr);
|
8.环境变量
用于环境变量的操作函数
#include <stdlib.h>
char *getenv(const char *name);
#include <stdlib.h> int putenv(char *str); int setenv(const char *name, const char *value, int rewrite); int unsetenv(const char *name);
9.setjmp和longjmp跨越函数跳转
#include <setjmp.h>
int setjmp(jmp_buf env);
|
Returns: 0 if called directly, nonzero if returning from a call to longjmp |
void longjmp(jmp_buf env, int val); |
例:
#include "apue.h" #include <setjmp.h> static void f1(int, int, int, int); static void f2(void); static jmp_buf jmpbuffer; static int globval; int main(void) { int autoval; register int regival; volatile int volaval; static int statval; globval = 1; autoval = 2; regival = 3; volaval = 4; statval = 5; if (setjmp(jmpbuffer) != 0) { printf("after longjmp:\n"); printf("globval = %d, autoval = %d, regival = %d," " volaval = %d, statval = %d\n", globval, autoval, regival, volaval, statval); exit(0); } /* * Change variables after setjmp, but before longjmp. */ globval = 95; autoval = 96; regival = 97; volaval = 98; statval = 99; f1(autoval, regival, volaval, statval); /* never returns */ exit(0); } static void f1(int i, int j, int k, int l) { printf("in f1():\n"); printf("globval = %d, autoval = %d, regival = %d," " volaval = %d, statval = %d\n", globval, i, j, k, l); f2(); } static void f2(void) { longjmp(jmpbuffer, 1); }
10.资源限制getrlimit和setrlimit
#include <sys/resource.h>
int getrlimit(int resource, struct rlimit *rlptr);
int setrlimit(int resource, const struct rlimit *rlptr);
例:
#include "apue.h" #if defined(BSD) || defined(MACOS) #include <sys/time.h> #define FMT "%10lld " #else #define FMT "%10ld " #endif #include <sys/resource.h> #define doit(name) pr_limits(#name, name) static void pr_limits(char *, int); int main(void) { #ifdef RLIMIT_AS doit(RLIMIT_AS); #endif doit(RLIMIT_CORE); doit(RLIMIT_CPU); doit(RLIMIT_DATA); doit(RLIMIT_FSIZE); #ifdef RLIMIT_LOCKS doit(RLIMIT_LOCKS); #endif #ifdef RLIMIT_MEMLOCK doit(RLIMIT_MEMLOCK); #endif doit(RLIMIT_NOFILE); #ifdef RLIMIT_NPROC doit(RLIMIT_NPROC); #endif #ifdef RLIMIT_RSS doit(RLIMIT_RSS); #endif #ifdef RLIMIT_SBSIZE doit(RLIMIT_SBSIZE); #endif doit(RLIMIT_STACK); #ifdef RLIMIT_VMEM doit(RLIMIT_VMEM); #endif exit(0); } static void pr_limits(char *name, int resource) { struct rlimit limit; if (getrlimit(resource, &limit) < 0) err_sys("getrlimit error for %s", name); printf("%-14s ", name); if (limit.rlim_cur == RLIM_INFINITY) printf("(infinite) "); else printf(FMT, limit.rlim_cur); if (limit.rlim_max == RLIM_INFINITY) printf("(infinite)"); else printf(FMT, limit.rlim_max); putchar((int)'\n'); }