基本概念
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 */
};
===============================================================================
![]()