Chinaunix首页 | 论坛 | 博客
  • 博客访问: 929062
  • 博文数量: 177
  • 博客积分: 8613
  • 博客等级: 中将
  • 技术积分: 2835
  • 用 户 组: 普通用户
  • 注册时间: 2006-03-12 04:16
文章分类
文章存档

2012年(12)

2011年(24)

2010年(24)

2009年(75)

2008年(42)

我的朋友

分类: C/C++

2009-11-18 23:03:14

   终于看到nice.c了,这个程序调用了一个系统调用nice,外加一个库函数execvp

/* nice -- run a program with modified niceness
 niceness的意思是:美好的事物,这是yodao词典解释出来的,意译一下,指的是,改变某个程序的优先级 */

/* David MacKenzie */
//包含4个标准库里的头文件
#include
#include
#include
#include
//包含本地的一个头文件,在这个软件包里,多处引用了这个头文件
#include "system.h"
//#if是条件编译指令,这里的意思是,如果HAVE_NICE是0,则包含进某个头文件来
#if ! HAVE_NICE
/* Include this after "system.h" so we're sure to have definitions
   (from time.h or sys/time.h) required for e.g. the ru_utime member.  */
# include
#endif
//继续包含本地的一些头文件
#include "error.h"
#include "long-options.h"
#include "quote.h"
#include "xstrtol.h"

/* The official name of this program (e.g., no `g' prefix).  */
#define PROGRAM_NAME "nice"//定义宏PROGRAM_NAME,其值是一个字符串

#define AUTHORS "David MacKenzie"//定义宏AUTHORS,其值也是一个字符串
//此处还是条件编译,如果HAVE_NICE的值不是0,则定义了一个宏GET_NICENESS()
#if HAVE_NICE
# define GET_NICENESS() nice (0)
#else//否则,用另一种方式来定义这个宏
# define GET_NICENESS() getpriority (PRIO_PROCESS, 0)
#endif//条件编译结束

#ifndef NZERO//如果没有定义宏NZERO,则将宏NZERO定义为20
# define NZERO 20
#endif//条件编译结束

/* This is required for Darwin Kernel Version 7.7.0.  */
#if NZERO == 0//这个小细节据作者的注释,是为了适应某个系统的,意思是,如果宏NZERO的值等于0,则将NZERO的值设置为20
# undef  NZERO
# define NZERO 20
#endif

/* The name this program was run with. */
char *program_name;//声明全局字符指针变量program_name,在main函数里会使用标准做法为这个变量赋值

static struct option const longopts[] =
{
  {"adjustment", required_argument, NULL, 'n'},
  {NULL, 0, NULL, 0}
};//初始化结构体数组,一看这形式,就是给命令行选项使用的,在这个coreutil软件包里,对命令行选项的处理,很是成熟啊,值得借鉴

void
usage (int status)//和之前的一样,帮助函数
{
  if (status != EXIT_SUCCESS)//如果传入的形参status不等于EXIT_SUCCESS,则向标准错误输出一个字符串,否则打印更详细的信息到标准输出
    fprintf (stderr, _("Try `%s --help' for more information.\n"),
         program_name);
  else
    {
      printf (_("Usage: %s [OPTION] [COMMAND [ARG]...]\n"), program_name);
      printf (_("\
Run COMMAND with an adjusted niceness, which affects process scheduling.\n\
With no COMMAND, print the current niceness.  Nicenesses range from\n\
%d (most favorable scheduling) to %d (least favorable).\n\
\n\
  -n, --adjustment=N   add integer N to the niceness (default 10)\n\
"),
          - NZERO, NZERO - 1);
      /*
这段输出描述了程序的主要作用,意思是,调整程序的优先级,这个优先级影响进程调度,如果没有程序名参数,打印现在的各个优先级,
优先级的范围是-20~20,默认是10,读到这里也明白了,原来这个20是由一个宏来定义的,之前几年所看到的20这个数字,原来出自这里,很开心的说^_^
      */
      fputs (HELP_OPTION_DESCRIPTION, stdout);
      fputs (VERSION_OPTION_DESCRIPTION, stdout);
      printf (USAGE_BUILTIN_WARNING, PROGRAM_NAME);
      printf (_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT);
    }
  exit (status);//调用帮助函数后,退出程序
}

int
main (int argc, char **argv)//标准main函数
{
  int current_niceness;//声明整型变量current_niceness
  int adjustment = 10;//初始化整型变量adjustment,猜测一下,应该是默认的优先级了吧
  char const *adjustment_given = NULL;//初始化一个指针,这个指针指向的是一个字符常量,指向的值不能被修改,但指针本身可以被修改
  bool ok;//nnd,又出来了布尔变量,真不爽啊
  int i;//声明整型变量
//下面的这5句话我们见了很多次了,不知道什么时候我写程序的时候才能用上呢
  initialize_main (&argc, &argv);
  program_name = argv[0];
  setlocale (LC_ALL, "");
  bindtextdomain (PACKAGE, LOCALEDIR);
  textdomain (PACKAGE);
//调用在system.h里面定义的宏
  initialize_exit_failure (EXIT_FAIL);
  atexit (close_stdout);//登记出口函数

  parse_long_options (argc, argv, PROGRAM_NAME, GNU_PACKAGE, VERSION,
              usage, AUTHORS, (char const *) NULL);//解析命令行参数,主要是为了打印帮助信息

  for (i = 1; i < argc; /* empty */)//这个循环共执行argc -1 次,如果argc是1,则不执行循环体了
    {
      char const *s = argv[i];//初始化局部变量s,其值是argv[i]的值
/*
为了理解这个if语句里的条件,我们一步步地来分析,首先,第一个条件是s[0] == '-' ,这个好理解,s是个指针,用数组的方式访问数组的第一个元素,也就是s所指向的字符串的第一个字符,如果它是'-',则此条件满足,继续下面的第二个条件判断;
第二个条件,先看括号里的最内层小括号:(s[1] == '-' || s[1] == '+'),这是两个逻辑表达式,如果有一个是1,则返回1,都是0的情况下才返回0,其字面含义是:如果s指向的字符串的第二个字符是加号或者减号,则这个小括号返回的值是1,否则返回0?小括号计算完毕后,和1相加,得到一个s的下标,然后调用ISDIGIT宏,来判断这个下标指向的字符串是否是数字
这里有必要回到system.h里面看看ISDIGIT宏的具体定义了:
#define ISDIGIT(c) ((unsigned int) (c) - '0' <= 9)
非常简单,就是将字符,或者字符串转换成整数,看是否小于等于9,这也说明不能是两位数,加或减,只能是个位数了
最后,如果这两个条件都满足,则执行下面的语句块,否则执行else里面的语句块
*/
      if (s[0] == '-' && ISDIGIT (s[1 + (s[1] == '-' || s[1] == '+')]))
    {
      adjustment_given = s + 1;//字符指针adjustment_given得到的值是s+1,去掉了s里的短横线
      ++i;//增加i的值,然后继续循环
    }
      else
    {//这个else代码段里最后也是通过命令行个数来得到一个adjustment_given的值,具体过程不再仔细说了,需要详细了解命令行选项的相关知识方可
      int optc;
      int fake_argc = argc - (i - 1);
      char **fake_argv = argv + (i - 1);

      /* Ensure that any getopt diagnostics use the right name.  */
      fake_argv[0] = program_name;

      /* Initialize getopt_long's internal state.  */
      optind = 0;

      optc = getopt_long (fake_argc, fake_argv, "+n:", longopts, NULL);
      i += optind - 1;

      if (optc == '?')
        usage (EXIT_FAIL);
      else if (optc == 'n')
        adjustment_given = optarg;
      else /* optc == -1 */
        break;
    }
    }

  if (adjustment_given)//如果adjustment_given不是空指针,则执行下面的代码
    {
      /* If the requested adjustment is outside the valid range,
     silently bring it to just within range; this mimics what
     "setpriority" and "nice" do.  */
     //初始化枚举变量
      enum { MIN_ADJUSTMENT = 1 - 2 * NZERO, MAX_ADJUSTMENT = 2 * NZERO - 1 };
      //声明一个长整型变量tmp
      long int tmp;
      //如果LONGINT_OVERFLOW的值小于调用xstrtol后的值,则调用error函数
      if (LONGINT_OVERFLOW < xstrtol (adjustment_given, NULL, 10, &tmp, ""))
    error (EXIT_FAIL, 0, _("invalid adjustment %s"),
           quote (adjustment_given));
      //调整后的adjustment值是调用了MAX和MIN宏之后的值,具体是这样的:先比较tmp和MAX_ADJUSTMENT,返回一个较小的值,然后用这个值和MIN_ADJUSTMENT进行比较,返回一个较大的值,MAX MIN都是宏定义的,比较方便,将来我应该多多借鉴啊,而且没有类型约束,整型,字符型都可以使用
      adjustment = MAX (MIN_ADJUSTMENT, MIN (tmp, MAX_ADJUSTMENT));
    }

  if (i == argc)//程序执行到这里,说明没有得到命令行参数
    {
      if (adjustment_given)//如果adjustment_given不是空指针,则调用error函数后打印帮助并退出程序
    {
      error (0, 0, _("a command must be given with an adjustment"));
      usage (EXIT_FAIL);
    }
      /* No command given; print the niceness.  */
      errno = 0;//将errno的值设为0
      current_niceness = GET_NICENESS ();//current_niceness得到的值,是通过宏GET_NICENESS ()得到的,这个宏是调用nice系统调用了
      if (current_niceness == -1 && errno != 0)//调用nice系统调用完毕后,判断current_niceness是否等于-1,errno是否被置为0,如果都是的话,调用error函数
    error (EXIT_FAIL, errno, _("cannot get niceness"));
      printf ("%d\n", current_niceness);//程序继续运行,打印得到的current_niceness整型值
      exit (EXIT_SUCCESS);//并成功退出程序
    }

  errno = 0;//重置errno变量,这个变量用来保存各种出错时候得到的值
#if HAVE_NICE//条件编译,如果用宏定义HAVE_NICE,值不为0,则调用nice,传的参数是上面得到的adjustment
  ok = (nice (adjustment) != -1 || errno == 0);//ok保存是是否成功进行了系统调用
#else//否则进行下面的操作:
  current_niceness = GET_NICENESS ();//调用宏GET_NICENESS ()给current_niceness赋值
  if (current_niceness == -1 && errno != 0)//如果current_niceness的值等于-1并且errno不等于0,则调用error函数
    error (EXIT_FAIL, errno, _("cannot get niceness"));
//ok保存的值是调用setpriority函数后得到的值
  ok = (setpriority (PRIO_PROCESS, 0, current_niceness + adjustment) == 0);
#endif//条件编译结束
  if (!ok)//如果ok是0,假的话,调用error函数
    error (errno == EPERM ? 0 : EXIT_FAIL, errno, _("cannot set niceness"));

  execvp (argv[i], &argv[i]);//运行后面接的程序,前面的是调节优先级,在这里实际的将程序切换到命令行参数所提供的程序了

  {//用条件语句得到exit_status的值
    int exit_status = (errno == ENOENT ? EXIT_ENOENT : EXIT_CANNOT_INVOKE);
    error (0, errno, "%s", argv[i]);//调用error函数
    exit (exit_status);//退出程序
  }
}

阅读(1411) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~