首页 > 代码库 > Linux环境

Linux环境

1. 程序参数

1.1 main 函数的形式

      查看C语言最新标准

  
int main () {/* ... */} // 为C++的标准
int main(int argc, char *argv[])  {/* ... */}  // 其中argc是程序参数的个数,argv代表参数自身的字符串数组。
main() {/* ... */}  // C90标准允许这种形式,但是C99标准不允许。因此即使你当前的编译器允许,也不要这么写。	
  main的参数通过另一个程序提供,这个程序一般为shell。   PS:Linux的shell一般设置argc和argv之前对文件名参数进行通配符扩展,MS-DOS的shell则期望程序接受带有通配符的参数 例如:$ myprog  left  right  ‘and center‘   main带的参数时:argc:4
argv: {"myprog", "left","right","and center"}.

1.2 getopt

  getopt用于解析命令行参数和可选字符的。
 getopt函数的使用选项:
#include <unistd.h>
int  getopt(int argc, char  *const arv[], const char *optsrting);
extern char *optarg;
extern int optind, opterr, optopt;

getopt()函数用于解析命令行参数。它的参数argc、argv就是main函数的参数,argc表示传给main函数的参数的个数(每一个参数都是字符串),argv则是一个char的指针数组,每一个指针数组的元素指向一个字符串参数。
在指针数组指向的字符串参数,如果以‘-‘开头,就表示这个字符串参数是一个“可选部分”‘-‘后面的那个字符就是一个“可选字符”。如果不断的调用getopt()函数,那么它每次从“可选部分”返回一个“可选字符”

变量optind是getopt要处理的argv中的下一个字符串参数的索引optind被系统初始化为1. 我们可以将它重新赋值为1,从而可以重新开始扫描指针数组argv。

每当getopt()函数找到一个“可选字符”,它就更新外部变量optind和一个内部静态变量nextchar,所以对getopt()函数的下一次调用可以从静态变量nextchar保存的位置开始。

当分析完了所有的“可选字符”时,getopt()函数返回-1. 同时optind的值正是数组argv中第一个非“可选部分”的索引,也就是说optind是第一个参数的索引

getopt()函数的第三个参数optstring是一个有所有合法的“可选字符”所组成的字符串。
《1》在参数optstring的“可选字符”如果后面带有一个‘:‘,则表示在该“可选字符”的后面必须有一个参数。比如“o:"表示: gcc -o arg 在-o的后面必须带有一个参数arg. 在getopt()函数解析完"o:"对应的命令行参数时,char型的指针optarg则指向了参数"arg"
《2》如果在“可选字符”的后面带有了两个‘:‘时,则表示在该“可选字符”后面可能有也可能没有参数,有参数,则optarg指向参数,没有则为0。这是GNU的一个关于getopt()函数的扩展。
《3》如果optstring中含有一个大写的‘W‘字符,后面带有一个冒号,也就是形如"W:",则表示该“可选字符”是一个“长选项”,也就是说不是只有一个字符的“可选字符”。比如:gcc -Wall  hello.c 要解析该命令行,getopt()函数中的第三个参数optstring应该是:"W:all",而且当解析到“-Wall"时optarg = "all".  这一点也是GNU对getopt()函数的扩展。
《4》如果getopt()函数在argv中解析到一个没有包含在optstring中的“可选字符”,它会打印一个错误信息,并将该“可选字符”保存在optopt中,并返回字符‘?‘。当然,我们可以将变量opterr赋值为0,来阻止getopt()函数输出错误信息
《5》当getopt()函数的第三个参数optstring的第一个字符是‘:‘时,很显然,这是由于少写了一个"可选字符"的缘故。此时,getopt()函数不返回‘?‘,而是返回‘:‘来暗示我们漏掉了一个”可选字符”.

/*************************************************************************
	> File Name: argopt.c
	> Author: qianlv
	> Mail: qianlv7@qq.com 
	> Created Time: 2014年04月30日 星期三 19时14分02秒
 ************************************************************************/

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>

int main(int argc, char *argv[])
{
    int opt;
    
    while((opt = getopt(argc,argv, ":qif:lr")) != -1){
        printf("optind:%d, opterr:%d, optopt:%c\n",optind,opterr,optopt);
        switch(opt){
        case ‘i‘:
        case ‘l‘:
        case ‘r‘:
        case ‘q‘:
            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;
        }
    }
    int result ;
    for(result = 0; result < argc; result ++) // 重写了argv数组,所有的非选项参数都集中在一起。
      printf("argv[%d] = %s ",result, argv[result]);
    printf("\n");
    for(;optind < argc; optind++)
      printf("argv[%d]=argument: %s\n", optind,argv[optind]);
    exit(0);
}
运行结果:$ ./argopt -i -lr ‘hi there‘  sjdf -f fred.c -q sfjkdjsf
optind:2, opterr:1, optopt:
option: i
optind:2, opterr:1, optopt:
option: l
optind:3, opterr:1, optopt:
option: r
optind:7, opterr:1, optopt:
filename: fred.c
optind:8, opterr:1, optopt:
option: q
argv[0] = ./argopt argv[1] = -i argv[2] = -lr argv[3] = -f argv[4] = fred.c argv[5] = -q argv[6] = hi there argv[7] = sjdf argv[8] = sfjkdjsf 
argv[6]=argument: hi there
argv[7]=argument: sjdf
argv[8]=argument: sfjkdjsf

1.3 . getopt_long

  #include <getopt.h>
   int getopt_long(int argc, char * const argv[],
   const char *optstring,
   const struct option *longopts, int *longindex);
  struct option {
       const char *name; // 长选项名字
       int has_arg;      // 该选项是否带参数。0不带参数,1必须带一个参数,2有一个可选的参数
       int *flag;        // 设置为NULL表示当找到该选项时,getopt_long返回在val里的值,否则getopt_long返回0,并将val的值写入flag指向的变量
       int val;          // getopt_long为该选项返回的值。
  };                     // 此数组最后一组数据必须全部填写0

    getopt_long 比getopt多俩个参数,第一个结构体数组,它描述了每个长选项并告诉如何处理他们。第二个附近参数是一个变量指针,如果它不为NULL,将把长选项数组中的下表索引写入该变量。
getopt_long_only函数,它与getopt_long函数使用相同的参数表,在功能上基本一致,只是getopt_long只将--name当作长参数,但getopt_long_only会将--name和-name两种选项都当作长参数来匹配。在getopt_long在遇到-name时,会拆解成-n -a -m -e到optstring中进行匹配,而getopt_long_only只在-name不能在longopts中匹配时才将其拆解成-n -a -m -e这样的参数到optstring中进行匹配。

/*************************************************************************
	> File Name: argopt2.c
	> Author: qianlv
	> Mail: qianlv7@qq.com 
	> Created Time: 2014年05月01日 星期四 09时36分40秒
 ************************************************************************/

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>

#define _GNU_SOURCE
#include<getopt.h>

int main(int argc, char *argv[])
{
    int opt;
    int list_test;
    struct option longopts[]= {
        {"initl",0,&list_test,‘i‘},
        {"file",1,&list_test,‘f‘},
        {"list",0,&list_test,‘l‘},
        {"restart",0,&list_test,‘r‘},
        {0,0,0,0}
    };
    int long_optind;
    while((opt = getopt_long(argc,argv,":if:lr", longopts, &long_optind)) != -1) {

        switch(opt){
        case 0: // 如果返回0,说明把值写入list_test中。比且通过long_optind索引访问对于长选项数组。
            printf("option: %c\n",list_test);
            printf("longopts: %s %d %c %c\n"
                    ,longopts[long_optind].name,longopts[long_optind].has_arg,
                    *longopts[long_optind].flag,longopts[long_optind].val
                    
                        );
            break;
        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("unknow option: %c\n",optopt);
            break;
        }
    }
    int i;
    for(i=0;i<argc;i++)
      printf("argv[%d] = %s ", i, argv[i]);
    puts("");

}
运行结果:./argopt2 one --initl two -l --file=fred.c -f three -l -q
option: i
longopts: initl 0 i i
option: l
option: f
longopts: file 1 f f
filename: three
option: l
unknow option: q
argv[0] = ./argopt2 argv[1] = --initl argv[2] = -l argv[3] = --file=fred.c argv[4] = -f argv[5] = three argv[6] = -l argv[7] = -q argv[8] = one argv[9] = two 

2. 环境变量

2.1 配置环境变量

#include<stdlib.h>
char *getenv(const char *name);// 查找环境中给定名字的环境变量的值,如果变量不存在或变量无关联值,返回NULL,PS:getenv返回的字符串是存储在getenv提供的静态空间中,如果想进一步使用它,就需将字符串复制到另一个字符串中,以免被后续的getenv调用覆盖。
int putenv(const char *string); //“名字=值”形式设置值 The putenv() function returns zero on success, or nonzero if  an  error occurs.
/*************************************************************************
  > File Name: environ.c
  > Author: qianlv
  > Mail: qianlv7@qq.com 
  > Created Time: 2014年05月01日 星期四 10时56分20秒
 ************************************************************************/

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>

int main(int argc, char *argv[])
{
    char *var, *value;
    if(argc == 1 || argc > 3){
        fprintf(stderr, "usage: environ var [value]\n");
        exit(1);
    }
    var = argv[1];
    value = http://www.mamicode.com/getenv(var);>

2.2 时间和日期

#include<time.h>
time_t time(time_t *tloc)  //返回从纪元(1970.1.1,0点)至今的秒数 time_t 为长整型long
double difftime(time_t time1, time_t time2);   // time1 - time2, 由于可移植性,最好使用difftime
struct tm *gmtime(const time_t *timeval);      // 把时间分解为格式struct tm 返回GMT时间
struct tm *localtime(const time_t *timeval);   // 返回当地时间
time_t mktime(struct tm *timeptr);             // 把struct tm结构时间转换为time_t时间
char *asctime(const struct tm *timeptr);       // 格式化为易读的时间格式:Thu May  1 14:52:43 2014\n\0
char *ctime(const time_t *timeval);            // 同上
struct tm
{
  int tm_sec;           /* Seconds. [0-60] (1 leap second) 允许临时闰秒或双闰秒*/ 
  int tm_min;           /* Minutes. [0-59] */
  int tm_hour;          /* Hours.   [0-23] */
  int tm_mday;          /* Day.     [1-31] */
  int tm_mon;           /* Month.   [0-11] 0表示1月*/
  int tm_year;          /* Year - 1900.  */
  int tm_wday;          /* Day of week. [0-6] 0表示周日*/
  int tm_yday;          /* Days in year.[0-365] */
  int tm_isdst;         /* DST.     [-1/0/1] 是否为夏令时*/

#ifdef  __USE_BSD
  long int tm_gmtoff;       /* Seconds east of UTC.  */
  __const char *tm_zone;    /* Timezone abbreviation.  */
#else
  long int __tm_gmtoff;     /* Seconds east of UTC.  */
  __const char *__tm_zone;  /* Timezone abbreviation.  */
#endif
};

/*************************************************************************
	> File Name: gmtime.c
	> Author: qianlv
	> Mail: qianlv7@qq.com 
	> Created Time: 2014年05月01日 星期四 14时30分01秒
 ************************************************************************/

#include<stdio.h>
#include<stdlib.h>
#include<time.h>

int main(void)
{
    struct tm *tm_ptr;
    time_t now_time;
    (void) time(&now_time);
    //tm_ptr = gmtime(&now_time); // 按照GMT(格林尼治标准时间)返回时间,可能与本地日期不相符。
    tm_ptr = localtime(&now_time); //当地时间
    printf("The date is : %s | %s | %s",ctime(&now_time),asctime(tm_ptr),asctime(gmtime(&now_time)));
    printf("Now time is %ld\n",now_time);
    printf("gmtime give:\n");
    printf("date: %02d/%02d/%02d\n",
                tm_ptr->tm_year,tm_ptr->tm_mon,tm_ptr->tm_mday);
    printf("time: %02d:%02d:%02d\n",
                tm_ptr->tm_hour,tm_ptr->tm_min,tm_ptr->tm_sec);
    exit(0);
}
/*
    运行结果:
    The date is : Thu May  1 14:56:52 2014
     | Thu May  1 14:56:52 2014
      | Thu May  1 14:56:52 2014
      Now time is 1398927412
      gmtime give:
    date: 114/04/01
    time: 14:56:52

 */
#include <time.h>
size_t strftime(char *s, size_t max, const char *format,const struct tm *tm);//针对时间的类似springf函数,通过format字符串格式化时间
#define _XOPEN_SOURCE       
#include <time.h>
char *strptime(const char *s, const char *format, struct tm *tm);  //类似sscanf通过format把字符串s格式化为struct tm的时间

3. 临时文件

#include <stdio.h>
char *tmpnam(char *s);//返回一个不与任何已存在文件同名的有效文件名,如果s不为NULL,文件也会写入它,它的长度至少为L_tmpnam(通常为20),此函数最多调用TMP_MAX次(至少为几千次)。应尽可能快地打开它以减小另一个程序用同样的名字打开文件的风险                     
FILE *tmpfile(void); //同时创建和打开一个临时文件,文件以读写的方式打开(w+),当对它的所有引用全部关闭时,该文件自动删除,如果出错返回NULL并设置errno的值。                                                                                                                              #include<stdlib.h>                                                                                                                  char *mktmep(char *template)  // The  last  six characters of template must be XXXXXX and these are replaced with a string that makes the filename  unique. 返回一个唯一的文件名                                                                                           int mkstemp(char *template)                                                                                                           /* The mkstemp() function generates a unique temporary filename from  tem‐
       plate,  creates and opens the file, and returns an open file descriptor
       for the file.

       The last six characters of template must  be  "XXXXXX"  and  these  are
       replaced  with  a string that makes the filename unique.  Since it will
       be modified, template must not be a  string  constant,  but  should  be
       declared as a character array.

       The file is created with permissions 0600, that is, read plus write for
       owner only. */
/*************************************************************************
	> File Name: tmpnam.c
	> Author: qianlv
	> Mail: qianlv7@qq.com 
	> Created Time: 2014年05月01日 星期四 16时22分20秒
 ************************************************************************/

#include<stdio.h>
#include<stdlib.h>

int main()
{
    char tmpname[L_tmpnam];
    char *filename;
    FILE *tmpfp;

    filename = tmpnam(tmpname);

    printf("Temporary file name is: %s\n",filename);
    tmpfp = tmpfile();
    if(tmpfp != NULL)
      printf("Opened a temporary file OK\n");
    else
      perror("tmpfile");
    exit(0);
}
/*
    运行结果:
    Temporary file name is: /tmp/file5zGzSJ
    Opened a temporary file OK
 */

4. 用户信息

#include<sys/types.h>
#include<unistd.h>
uid_t getuid(void); //returns the real user ID of the calling process.
uid_t geteuid(void);//returns the effective user ID of the calling process. 两者区别:http://www.cppblog.com/converse/archive/2007/12/20/39166.html                                        
char *getlogin(void);  /*returns  a  pointer  to a string containing the name of the user logged in on the controlling terminal of the process,  or  a  NULL pointer if this information cannot be determined.*/
#include<pwd.h>
struct passwd *getpwuid(uid_t uid);
struct passwd *getpwnam(const char *name);   //出错时返回NULL,并设置errno
struct passwd {
               char   *pw_name;       /* username */
               char   *pw_passwd;     /* user password */
               uid_t   pw_uid;        /* user ID */
               gid_t   pw_gid;        /* group ID */
               char   *pw_gecos;      /* user information */
               char   *pw_dir;        /* home directory */
               char   *pw_shell;      /* shell program */
           };                                                                                                                       struct passwd *getpwent(void);/*依次扫描密码文件返回每个用户的信息数据,当到达文件尾时,返回NULL,可以用endpwent函数终止,setpwent重置读取指针到密码文件开头。*/                                                                                                                        void endpwent(void);                                                                                                                void setpwent(void);       

5. 主机信息

#include<unistd.h>
int gethostname(char *name, size_t namelen); // 把机器的网络名写入name,且该字符串至少有namelen长。成功返回0,失败返回-1
#include<sys/utsname.h>
int uname(struct utsname *name);  //成功返回非负整数,否则返回-1并设置errno。
struct utsname {
               char sysname[];    /* Operating system name (e.g., "Linux") */
               char nodename[];   /* Name within "some implementation-defined
                                     network" */
               char release[];    /* OS release (e.g., "2.6.28") */
               char version[];    /* OS version */
               char machine[];    /* Hardware identifier */
           #ifdef _GNU_SOURCE
               char domainname[]; /* NIS or YP domain name */
           #endif
           };                                                                                                      long gethostid(void) //获取机器的唯一标识符