Linux-C编程-环境编程

1,程序参数

1.1 函数getopt

getopt()用来分析命令行参数。

头文件:
#include<unistd.h>
函数原型:
int getopt(int argc, char *const argv[], const char *optstring);
extern char *optarg;
extern int optind, opterr, optopt;
参数说明:
argc:是由main()传递的参数个数。
argv:是由main()传递的参数内容。
optstring:为选项字符串,该字符串告诉getopt哪些选项可用,以及每个选项是否有关联值。 optstring只是一个字符列表,每个字符代表一个单字符选项。如果一个字符后面紧跟一个冒号(:),则表明该选项有一个关联值作为下一个参数。
返回值:getopt的返回值是argv数组中的下一个选项字符(如果有的话)。循环调用getopt就可以依次得到每个选项。getopt有如下行为:
l 如果选项有一个关联值,则外部变量optarg指向这个值。
l 如果选项处理完毕,getopt返回-1,特殊参数--将使getopt停止扫描选项的工作。
l 如果遇到一个无法识别的选项,getopt返回一个问号(?),并把它保存到外部变量optopt中。
l 如果一个选项要求有一个关联值,但未提供这个值,则getopt将返回一个冒号(:)。
optarg——指向当前选项参数(如果有)的指针。 
optind——再次调用 getopt() 时的下一个 argv 指针的索引。 
optopt——最后一个已知选项。
样例程序:

#include <stdio.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
    int opt;
    while((opt = getopt(argc, argv, “if:lr”)) != -1) {
        switch(opt) {
        case ‘i’:
        case ‘l’:
        case ‘r’:
            printf(“option: %c/n”, opt);
            break;
        case ‘f’:
            printf(“filename: %s/n”, optarg);
            break;
        case ‘:’:
            printf(“option needs a value/n”);
            break;
        case ‘?’:
            printf(“unknown option: %c/n”, optopt);
            break;
        }
    }
    for(; optind < argc; optind++)
        printf(“argument: %s/n”, argv[optind]);
    exit(0);
}
现在,当我们运行这个程序时,我们发现所有的命令行参数被自动处理了:
$ ./argopt -i -lr ‘hi there’ -f fred.c -q
option: i
option: l
option: r
filename: fred.c
argopt: invalid option-—q
unknown option: q
argument: hi there

1.2 函数getopt_long

许多Linux程序同时会接受比我们在上面的例子中所使用的单字符选项更有意义的参数。GNU C库包含一个被称之为getopt_long的getopt版本,他可以接受由双短划线引入的所谓长参数

头文件:
#include<unistd.h>
函数原型:
int getopt_long(int argc, char * const argv[],const char *optstring, const struct option *longopts, int *longindex);
int getopt(int argc, char *const argv[], const char *optstring);
extern char *optarg;
extern int optind, opterr, optopt;
参数说明:
argc:是由main()传递的参数个数。
argv:是由main()传递的参数内容。
optstring:可以下列元素:
1.单个字符,表示选项,
2.单个字符后接一个冒号:表示该选项后必须跟一个参数。参数紧跟在选项后或者以空格隔开。该参数的指针赋给optarg。
3 单个字符后跟两个冒号,表示该选项后可以有参数也可以没有参数。如果有参数,参数必须紧跟在选项后不能以空格隔开。该参数的指针赋给optarg。(这个特性是GNU的扩张)。
optstring是一个字符串,表示可以接受的参数。例如,"a:b:cd",表示可以接受的参数是a,b,c,d,其中,a和b参数后面跟有更多的参数值。(例如:-a host -b name)
longopts:其实是一个结构的实例:
struct option {
const char *name; //name表示的是长参数名
int has_arg; //has_arg有3个值:  no_argument(或者是0),表示该参数后面不跟参数值
                                                   required_argument(或者是1),表示该参数后面一定要跟个参数值
                                                   optional_argument(或者是2),表示该参数后面可以跟,也可以不跟参数值
int *flag;//用来决定,getopt_long()的返回值到底是什么。如果flag是null,则函数会返回与该项option匹配的val值
int val; //和flag联合决定返回值
}
l 如果选项有一个关联值,则外部变量optarg指向这个值。
l 如果选项处理完毕,getopt返回-1,特殊参数--将使getopt停止扫描选项的工作。
l 如果遇到一个无法识别的选项,getopt返回一个问号(?),并把它保存到外部变量optopt中。
l 如果一个选项要求有一个关联值,但未提供这个值,则getopt将返回一个冒号(:)。
optarg——指向当前选项参数(如果有)的指针。 
optind——再次调用 getopt() 时的下一个 argv 指针的索引。 
optopt——最后一个已知选项。
示例程序

#include <stdio.h>
#include <unistd.h>
#define _GNU_SOURCE
#include <getopt.h>
int main(int argc, char *argv[])
{
    int opt;
  struct option longopts[] = {
      {“initialize”, 0, NULL, ‘i’},
      {“file”, 1, NULL, ‘f’},
      {“list”, 0, NULL, ‘l’},
      {“restart”, 0, NULL, ‘r’},
      {0,0,0,0}};
  while((opt = getopt_long(argc, argv, “if:lr”, longopts, NULL)) != -1) {
      switch(opt) {
      case ‘i’:
      case ‘l’:
      case ‘r’:
          printf(“option: %c/n”, opt);
          break;
      case ‘f’:
          printf(“filename: %s/n”, optarg);
          break;
      case ‘:’:
          printf(“option needs a value/n”);
          break;
      case ‘?’:
          printf(“unknown option: %c/n”, optopt);
          break;
      }
  }
  for(; optind < argc; optind++)
      printf(“argument: %s/n”, argv[optind]);
  exit(0);
}
测试结果:

$ ./longopt —init –l —file=fred.c ‘hi there’
option: i
option: l
filename: fred.c
argument: hi there

2,环境变量

临时文件的大量使用隐藏了他的一个缺点。我们必须小心来确保程序会选择一个唯一的名字来使用临时文件。如果不是这样,因为Linux是一个多任务系统,也许会有另一个程序选择了相同的名字,而这两个彼此之间会相互影响。

2.1 函数tmpnam

返回一个唯一的文件名(路径名),注意只是文件名,不是文件,所以还需要创建,打开和关闭。

头文件:
#include <stdio.h>
函数原型:
char *tmpnam(char *sptr);
参数说明:
sptr:
sptr为NULL时,返回一个内部静态内存地址(保存了临时文件名),当下一次以NULL调用函数的时候,该内存会被修改。
sptr不为NULL,则返回的文件名也存储在sptr所指向的用户定义内存中,栈地址必须至少有L_tmpnam内存,注意用此文件名去打开文件流所创建的文件都是临时性的。
返回值:产生一个唯一的文件名字符串
tmpnam可以被一个程序最多调用TMP_MAX(最少为几千次),每一次它都会返回一个不同的文件名。
调用tmpnam生成一个唯一文件名的临时文件。如果我们要使用这个临时文件,我们可以立即打开,从而来减小另一个程序会使用同一个文件名打开这个文件的风险。

2.2 函数tmpfile

tmpfile函数会返回一个指向唯一的临时文件的流指针。这个文件会以读和写打开,而且在所有到文件的引用被关闭以后,这个文件会被自动删除。

头文件:
#include <stdio.h>
函数原型:
FILE *tmpfile(void);
返回值:产生一个唯一的文件流,如果发生错误,tmpfile会返回一个空指针,并且设置errno变量。
tmpfile函数的实现原理是:tmpfile函数先调用tmpnam产生一个唯一的路径名,然后,用该路径创建一个二进制文件,并且立即unlink它。
示例代码:

#include <stdlib.h>
int main(void)
{
	FILE *tempfp;
	tempfp = tmpfile();
	if (tempfp)
		printf("Temporary file created\n");
	else
	{
		printf("Unable to create temporary file\n");
		exit(1);
	}
	return 0;
}


3,日志信息

常见使用范例:
#include <syslog.h>

int main(int argc, char **argv) {
    openlog("myProg", LOG_CONS | LOG_PID, 0);
    syslog(LOG_INFO,
           "This is a syslog test message generated by program %s\n",
           argv[0]);
    closelog();
    return 0;
}

3.1 函数openlog

调用openlog是可选择的。如果不调用openlog,则在第一次调用syslog时,自动调用openlog。调用closelog也是可选择的,它只是关闭被用于与syslog守护进程通信的描述符。调用openlog 使我们可以指定一个ident,以后, 此ident 将被加至每则记录消息中。ident 一般是程序的名称(例如 ,cron ,ine 等)。
头文件:
#include <syslog.h>
函数原型: 
void openlog (char*ident, int option, int facility); 
参数说明:
第一个参数ident将是一个标记,ident所表示的字符串将固定地加在每行日志的前面以标识这个日志,通常就写成当前程序的名称以作标记。
第二个参数option是下列值取与运算的结果:默认值LOG_USER
LOG_CONS        直接写入系统控制台,如果有一个错误,同时发送到系统日志记录。
LOG_NDELAY    立即打开连接(通常,打开连接时记录的第一条消息)。
LOG_NOWAIT   不要等待子进程,因为其有可能在记录消息的时候就被创建了(GNU C库不创建子进程,所以该选项在Linux上没有影响。)
LOG_ODELAY    延迟连接的打开直到syslog函数调用。(这是默认情况下,需要没被指定的情况下。)
LOG_PERROR   (不在SUSv3情况下)同时输出到stderr(标准错误文件)。
LOG_PID          包括每个消息的PID。

第三个参数facility是用来指定记录消息程序的类型。它让指定的配置文件,将以不同的方式来处理来自不同方式的消息。
LOG_AUTH ——认证系统:login、su、getty等 
LOG_AUTHPRIV ——同LOG_AUTH,但只登录到所选择的单个用户可读的文件中 
LOG_CRON           ——cron守护进程 
LOG_DAEMON       ——其他系统守护进程,如routed 
LOG_FTP ——文件传输协议:ftpd、tftpd 
LOG_KERN ——内核产生的消息 
LOG_LPR ——系统打印机缓冲池:lpr、lpd 
LOG_MAIL ——电子邮件系统 
LOG_NEWS ——网络新闻系统 
LOG_SYSLOG ——由syslogd(8)产生的内部消息 
LOG_USER ——随机用户进程产生的消息 
LOG_UUCP ——UUCP子系统 
LOG_LOCAL0~LOG_LOCAL7 ——为本地使用保留 
Syslog为每个事件赋予几个不同的优先级: 
LOG_EMERG ——紧急情况 
LOG_ALERT ——应该被立即改正的问题,如系统数据库破坏 
LOG_CRIT ——重要情况,如硬盘错误 
LOG_ERR ——错误 
LOG_WARNING ——警告信息 
LOG_NOTICE ——不是错误情况,但是可能需要处理 
LOG_INFO ——情报信息 
LOG_DEBUG ——包含情报的信息,通常旨在调试一个程序时使用 


3.2 函数syslog

通常,日志信息会记录在一个目录中的一个系统文件中。这也许是/var/log。在通常的Linux安装中, /var/log/messages文件包含系统信息,/var/log/mail包含其他的邮件系统的日志信息,/var/log/debug包含调试 信息。我们可以在/etc/syslog.conf文件中查看我们的系统配置。

头文件:
#include <syslog.h>
函数原型: 
int syslog(int priority, string message);
参数说明:
priority:值可能为 LOG_EMERG、LOG_ALERT、LOG_CRIT、LOG_ERR、LOG_WARNING、LOG_NOTICE、LOG_INFO、 LOG_DEBUG。本函数呼叫 UNIX 操作系统的 syslog() 函数,在 Windows NT 上,使用事件检视器模拟出本功能。
syslog为每个事件赋予几个不同的优先级:
LOG_EMERG:紧急情况,需要立即通知技术人员。
LOG_ALERT:应该被立即改正的问题,如系统数据库被破坏,ISP连接丢失。
LOG_CRIT:重要情况,如硬盘错误,备用连接丢失。
LOG_ERR:错误,不是非常紧急,在一定时间内修复即可。
LOG_WARNING:警告信息,不是错误,比如系统磁盘使用了85%等。
LOG_NOTICE:不是错误情况,也不需要立即处理。
LOG_INFO:情报信息,正常的系统消息,比如骚扰报告,带宽数据等,不需要处理。
LOG_DEBUG:包含详细的开发情报的信息,通常只在调试一个程序时使用。
message:要写入的信息
示例代码:

#include <syslog.h>
#include <stdio.h>
int main()
{
    FILE *f;
    f = fopen(“not_here”,”r”);
    if(!f)
        syslog(LOG_ERR|LOG_USER,”oops - %m/n”);
    exit(0);
}

3.3 函数closelog

头文件:
#include <syslog.h>
函数原型: 
void closelog();











你可能感兴趣的:(Linux-C编程-环境编程)