终于看到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) |