基本概念
main 函数
命令行参数及 popt 库
环境变量
C 程序的内存布局
共享库
内存分配
程序的长跳转
进程的资源限制
=============================================================================== int main (int argc, char *argv[]); ===============================================================================
=============================================================================== #include <stdlib.h> void exit (int status); #include <unistd.h> void _exit (int status); ===============================================================================
=============================================================================== #include <stdlib.h> int atexit (void (*function) (void)); ===============================================================================
=============================================================================== GNU 风格的命令行参数特点: * 长参数名, 比如, --binary, 但对应有短参数, 比如, -b ===============================================================================
=============================================================================== #include <popt.h> poptContext poptGetContext (char * name, int argc, char ** argv, struct poptOption * options, int flags); void poptFreeContext (poptContext con); void poptResetContext (poptContext con); int poptGetNextOpt (poptContext con); char * poptGetOptArg (poptContext con); char * poptGetArg (poptContext con); ...... ------------------------------------------------------------------------------- EXAMPLE: /* This example comes from popt(3) man page. */ #include <popt.h> #include <stdio.h> void usage (poptContext optCon, int exitcode, char *error, char *addl) { poptPrintUsage (optCon, stderr, 0); if (error) fprintf (stderr, "%s: %s", error, addl); exit (exitcode); } int main (int argc, char *argv[]) { char c; /* used for argument parsing */ int i = 0; /* used for tracking options */ char *portname; int speed = 0; /* used in argument parsing to set speed */ int raw = 0; /* raw mode? */ int j; char buf[BUFSIZ+1]; poptContext optCon; /* context for parsing command-line options */ struct poptOption optionsTable[] = { { "bps", 'b', POPT_ARG_INT, &speed, 0, "signaling rate in bits-per-second", "BPS" }, { "crnl", 'c', 0, 0, 'c', "expand cr characters to cr/lf sequences" }, { "hwflow", 'h', 0, 0, 'h', "use hardware (RTS/CTS) flow control" }, { "noflow", 'n', 0, 0, 'n', "use no flow control" }, { "raw", 'r', 0, &raw, 0, "don't perform any character conversions" }, { "swflow", 's', 0, 0, 's', "use software (XON/XOF) flow control" } , POPT_AUTOHELP { NULL, 0, 0, NULL, 0 } }; optCon = poptGetContext(NULL, argc, argv, optionsTable, 0); poptSetOtherOptionHelp(optCon, "[OPTIONS]* <port>"); if (argc < 2) { poptPrintUsage(optCon, stderr, 0); exit(1); } /* Now do options processing, get portname */ while ((c = poptGetNextOpt(optCon)) >= 0) { switch (c) { case 'c': buf[i++] = 'c'; break; case 'h': buf[i++] = 'h'; break; case 's': buf[i++] = 's'; break; case 'n': buf[i++] = 'n'; break; } } portname = poptGetArg (optCon); if((portname == NULL) || !(poptPeekArg (optCon) == NULL)) usage (optCon, 1, "Specify a single port", ".e.g., /dev/cua0"); if (c < -1) { /* an error occurred during option processing */ fprintf(stderr, "%s: %s\n", poptBadOption (optCon, POPT_BADOPTION_NOALIAS), poptStrerror (c)); return 1; } /* Print out options, portname chosen */ printf ("Options chosen: "); for (j = 0; j < i ; j++) printf ("-%c ", buf[j]); if (raw) printf("-r "); if (speed) printf("-b %d ", speed); printf ("\nPortname chosen: %s\n", portname); poptFreeContext (optCon); exit (0); } --------------------------------------- $ ./popt --usage Usage: popt [-chnrs?] [-b BPS] [--usage] [OPTIONS]* <port> $ ./popt -c -b 9600 /dev/cua0 Options chosen: -c -b 9600 Portname chosen: /dev/cua0 ===============================================================================
=============================================================================== #include <stdlib.h> char *getenv (const char *name); int putenv (const char *string); int setenv (const char *name, const char *value, int overwrite); void unsetenv (const char *name); ===============================================================================
=============================================================================== ----------------- 高地址 | | ---> 命令行参数和环境变量 (只读) ----------------- | 栈 | |- - - - - - - -| | | | | | \ / | | | | | | / \ | | | | | |- - - - - - - -| | 堆 | |---------------| | 未初始化数据 | | (bss) | ---> 由 exec 初始化为零 |---------------| | 初始化后数据 | \ |---------------| | | text | | 由 exec 从程序中读取 低地址 | | / |---------------| ===============================================================================
=============================================================================== #include <stdlib.h> void *calloc (size_t nmemb, size_t size); void *malloc (size_t size); void free (void *ptr); void *realloc (void *ptr, size_t size); ------------------------------------------------------------------------------- * calloc 分配后的数据被设置为 0. * malloc 分配的数据不清除. * free (NULL) 是合法的. * realloc 新分配的区域不经过初始化. ===============================================================================
=============================================================================== #include <stdlib.h> void *alloca( size_t size); ------------------------------------------------------------------------------- * alloca 在栈中分配, 不需要释放, 函数返回时自动释放. * 在某些系统的线程库实现中, 要注意每个线程的栈大小有限制. ===============================================================================
=============================================================================== #include <setjmp.h> int setjmp (jmp_buf env); void longjmp (jmp_buf env, int val); ------------------------------------------------------------------------------- EXAMPLE: /* C 程序的长跳转 */ #include <stjmp.h> jmp_buf jmpbuffer; int main (void) { char line [MAXLINE]; switch (setjmp (jmpbuffer)) { case 0: break; case 1: break; default: break; } return 0; } void some_func (void) { if (...) longjmp (jmpbuffer, 0); else if (...) longjmp (jmpbuffer, 1); else longjmp (jmpbuffer, 2); } ------------------------------------------------------------------------------- * jmpbuffer 必须是全局变量. * 注意在长跳转返回之后, 对不同类型的 (自动, 寄存器, 非易失) 变量处理不同. 非易失变量不会发生改变, 但自动变量和寄存器变量可能要恢复为调用 setjmp 之前 的值. ===============================================================================
=============================================================================== #include <sys/time.h> #include <sys/resource.h> #include <unistd.h> int getrlimit (int resource, struct rlimit *rlim); int getrusage (int who, struct rusage *usage); int setrlimit (int resource, const struct rlimit *rlim); ------------------------------------------------------------------------------- struct rlimit { int rlim_cur; int rlim_max; }; struct rusage { struct timeval ru_utime; /* user time used */ struct timeval ru_stime; /* system time used */ long ru_maxrss; /* maximum resident set size */ long ru_ixrss; /* integral shared memory size */ long ru_idrss; /* integral unshared data size */ long ru_isrss; /* integral unshared stack size */ long ru_minflt; /* page reclaims */ long ru_majflt; /* page faults */ long ru_nswap; /* swaps */ long ru_inblock; /* block input operations */ long ru_oublock; /* block output operations */ long ru_msgsnd; /* messages sent */ long ru_msgrcv; /* messages received */ long ru_nsignals; /* signals received */ long ru_nvcsw; /* voluntary context switches */ long ru_nivcsw; /* involuntary context switches */ }; ===============================================================================