2004年10月11日

gcc的参数 -I (i)nclude 指出头文件的目录
  -L (l)ib 指出库函数的目录
ar工具可以生成静态库, libxxx.a a–archive
静态库和动态库存放在同一个目录下,只是后缀不同

2004年09月28日

Debian 目前有 Woody(stable)、Sarge(testing)、SID(unstable) 三个版本。Woody 的软件太旧,不适合做桌面。SID 的软件非常新,但易用性和稳定性不如 Sarge。Sarge 的软件比较新,并且易用性和稳定性都非常不错。本位采用 Sarge 做为桌面系统。

2004年09月20日

bluez-utils->main->

while ((opt=getopt_long(argc, argv, main_sopts, main_lopts, NULL)) != -1) {

getopt_long and getopt函数的man手册在

http://jamesthornton.com/linux/man/getopt_long.3.html

Name

getopt – Parse command line options 解析命令行参数(选项)

Synopsis(语法)

#include  int getopt(int argc, char * const argv[], const char *optstring); extern char *optarg;extern int optind, opterr, optopt; #define _GNU_SOURCE #include  int getopt_long(int argc, char * const argv[], const char *optstring, const struct option *longopts, int *longindex); int getopt_long_only(int argc, char * const argv[], const char *optstring, const struct option *longopts, int *longindex);

Description

The getopt() function parses the command line arguments. Its arguments argc and argv are the argument count and array as passed to the main() function on program invocation. An element of argv that starts with `-’ (and is not exactly “-” or “–”) is an option element. The characters of this element (aside from the initial `-’) are option characters.//argv以’-'开始的元素叫一个选项单元,这个元素的字符(除去’-'的部分)叫选项字符。

 If getopt() is called repeatedly, it returns successively each of the option characters from each of the option elements.

重复的调用getopt(),它会依次返回每一个选项单元的选项字符。

If getopt() finds another option character, it returns that character, updating the external variable optind and a static variable nextchar so that the next call to getopt() can resume the scan with the following option character or argv-element.

如果getopt()又发现了一个选项字符,它就返回这个字符,更新全局变量optind和静态变量nextchar,这样下次调用getopt()时会接着扫瞄剩下的选项字符。

If there are no more option characters, getopt() returns -1. Then optind is the index in argv of the first argv-element that is not an option.

如果再扫瞄不到选项字符,getopt()返回-1。optind是第一个不是选项的argv字符数组的下标。

optstring is a string containing the legitimate option characters.

optstring是包含合法选项字符的字符串。

 If such a character is followed by a colon, the option requires an argument, so getopt places a pointer to the following text in the same argv-element, or the text of the following argv-element, in optarg.

如果这个字符串中的字符后紧跟一个冒号(;),说明这个选项需要一个参数,则getopt函数就将指向与这个字符是同一个argv单元的紧跟着的文本的指针存放在参数optarg中。

 Two colons mean an option takes an optional arg; if there is text in the current argv-element, it is returned in optarg, otherwise optarg is set to zero. This is a GNU extension. If optstring contains W followed by a semicolon, then -W foo is treated as the long option –foo. (The -W option is reserved by POSIX.2 for implementation extensions.) This behaviour is a GNU extension, not available with libraries before GNU libc 2.

两个冒号表示这个选项可以有一个可选的参数,如果有的话,就由optarg返回,否则optarg为零。

By default, getopt() permutes the contents of argv as it scans, so that eventually all the non-options are at the end. Two other modes are also implemented. If the first character of optstring is `+’ or the environment variable POSIXLY_CORRECT is set, then option processing stops as soon as a non-option argument is encountered. If the first character of optstring is `-’, then each non-option argv-element is handled as if it were the argument of an option with character code 1. (This is used by programs that were written to expect options and other argv-elements in any order and that care about the ordering of the two.) The special argument `–’ forces an end of option-scanning regardless of the scanning mode.

If getopt() does not recognize an option character, it prints an error message to stderr, stores the character in optopt, and returns `?’. The calling program may prevent the error message by setting opterr to 0.

如果getopt()不认识你给的选项字符,它向stderr打印一条错误信息,并将这个选项字符存在optopt中,并且返回’?'。

If getopt() finds an option character in argv that was not included in optstring, or if it detects a missing option argument, it returns `?’ and sets the external variable optopt to the actual option character.

If the first character of optstring is a colon (`:’), then getopt() returns `:’ instead of `?’ to indicate a missing option argument. If an error was detected, and the first character of optstring is not a colon, and the external variable opterr is nonzero (which is the default), getopt() prints an error message.

The getopt_long() function works like getopt() except that it also accepts long options, started out by two dashes. Long option names may be abbreviated if the abbreviation is unique or is an exact match for some defined option. A long option may take a parameter, of the form –arg=param or –arg param.

getopt_long()函数的工作方式与getopt()相同,除了它还可以处理长选项参数(由–开始)。

longopts is a pointer to the first element of an array of struct option declared in as

struct option { const char *name; int has_arg; int *flag; int val; };
static struct option main_lopts[] = { { "help",     0, 0, 'h' }, { "listen",   0, 0, 's' }, { "connect",  1, 0, 'c' }, { "search",   2, 0, 'Q' }, { "kill",     1, 0, 'k' }, { "killall",  0, 0, 'K' }, { "role",     1, 0, 'r' }, { "service",  1, 0, 'd' }, { "device",   1, 0, 'i' }, { "source",   1, 0, 'S' }, { "nosdp",    0, 0, 'D' }, { "list",     0, 0, 'l' }, { "show",     0, 0, 'l' }, { "nodetach", 0, 0, 'n' }, { "persist",  2, 0, 'p' }, { "encrypt",  0, 0, 'E' }, { "master",   0, 0, 'M' }, { "cache",    0, 0, 'C' }, { "pidfile",  1, 0, 'P' }, { "autozap",  0, 0, 'z' }, { 0, 0, 0, 0 }};
由于main_lopt的flag都是0,所以getopt_long()函数返回val,
注意到结构option的name成员和val成员的对应关系,
name: 长选项 ----val:短选项
 while ((opt=getopt_long(argc, argv, main_sopts, main_lopts, NULL)) != -1) {  switch(opt) {  case 'l':   mode = SHOW;   detach = 0;   break;
  case 's':   mode = LISTEN;   break;
  case 'c':   mode = CONNECT;   dst  = strdup(optarg);   break;
//注意这里的c带一个参数,当前的optarg指向那个参数,
The strdup() function returns a pointer to a new string 
which is a duplicate of the string s. 
static char main_sopts[] = "hsc:k:Kr:i:S:lnp::DQ::EMC::P:z";

The meanings of the different fields are:

name
is the name of the long option.
has_arg
is: no_argument (or 0) if the option does not take an argument, required_argument (or 1) if the option requires an argument, or optional_argument (or 2) if the option takes an optional argument.
0:这个长选项不需要参数
1:需要一个参数
2:有一个可选参数
flag
specifies how results are returned for a long option. If flag is NULL, then getopt_long() returns val. (For example, the calling program may set val to the equivalent short option character.) Otherwise, getopt_long() returns 0, and flag points to a variable which is set to val if the option is found, but left unchanged if the option is not found.
定义长选项的结果如何返回。如果flag等于NULL,那么getopt_long返回val。否则,getopt_long()返回0,flag指向一个变量,如果扫瞄到这个选项,这个变量设置为val,否则这个变量的值保持不变。
val
is the value to return, or to load into the variable pointed to by flag.

The last element of the array has to be filled with zeroes.

int getopt_long(int argc, char * const argv[],           const char *optstring,
          const struct option *longopts, int *longindex);

If longindex is not NULL, it points to a variable which is set to the index of the long option relative to longopts.

getopt_long_only() is like getopt_long(), but `-’ as well as `–’ can indicate a long option. If an option that starts with `-’ (not `–’) doesn’t match a long option, but does match a short option, it is parsed as a short option instead.

Return Value

The getopt() function returns the option character if the option was found successfully, `:’ if there was a missing parameter for one of the options, `?’ for an unknown option character, or -1 for the end of the option list.

getopt_long() and getopt_long_only() also return the option character when a short option is recognized. For a long option, they return val if flag is NULL, and 0 otherwise. Error and -1 returns are the same as for getopt(), plus `?’ for an ambiguous match or an extraneous parameter.

getopt_long()当识别了一个短选项时,也返回这个选项字符。对于长选项,如果flag等于NULL,返回val,否则返回0。

Environment Variables

POSIXLY_CORRECT
If this is set, then option processing stops as soon as a non-option argument is encountered.
_ _GNU_nonoption_argv_flags_
This variable was used by bash 2.0 to communicate to GNU libc which arguments are the results of wildcard expansion and so should not be considered as options. This behaviour was removed in bash version 2.01, but the support remains in GNU libc.

Example

The following example program illustrates the use of getopt_long() with most of its features.

#include  /* for printf */ 
#include  /* for exit */ 
#include  int main (int argc, char **argv) 
{ int c; 
int digit_optind = 0; 
while (1) 
{ int this_option_optind = optind ? optind : 1; 
int option_index = 0; 
static struct option long_options[] = 
{ {"add", 1, 0, 0}, 
{"append", 0, 0, 0}, 
{"delete", 1, 0, 0}, 
{"verbose", 0, 0, 0}, 
{"create", 1, 0, 'c'}, 
{"file", 1, 0, 0}, 
{0, 0, 0, 0} }; 
c = getopt_long (argc, argv, "abc:d:012",短选项 
long_options, &option_index); 
if (c == -1) break; 
switch (c) { 
case 0: printf ("option %s", long_options[option_index].name);
            返回0的情况出现在长选项中,当flag不等于NULL时 
if (optarg) printf (" with arg %s", optarg); printf ("\n"); break; 
case '0': 
case '1': 
case '2': 
if (digit_optind != 0 && digit_optind != this_option_optind) 
printf ("digits occur in two different argv-elements.\n"); 
digit_optind = this_option_optind; 
printf ("option %c\n", c); break; 
case 'a': printf ("option a\n"); 
break; case 'b': printf ("option b\n"); break; case 'c': printf ("option c with value `%s'\n", optarg); break; case 'd': printf ("option d with value `%s'\n", optarg); break; case '?': break; default: printf ("?? getopt returned character code 0%o ??\n", c); } } if (optind < argc) { printf ("non-option ARGV-elements: "); while (optind < argc) printf ("%s ", argv[optind++]); printf ("\n"); } exit (0); } 

Bugs

The POSIX.2 specification of getopt() has a technical error described in POSIX.2 Interpretation 150. The GNU implementation (and probably all other implementations) implements the correct behaviour rather than that specified.

Conforming to

getopt():
POSIX.2, provided the environment variable POSIXLY_CORRECT is set. Otherwise, the elements of argv aren’t really const, because we permute them. We pretend they’re const in the prototype to be compatible with other systems.
2004年09月19日



关于驱动程序中的ioctl


coly(李勇)[本站会员]

  我这里说的ioctl函数是在驱动程序里的,因为我不知道还有没有别的场合用到了ioctl, 所以就规定了我们讨论的范围。为什么要写篇文章呢,是因为我前一阵子被ioctl给搞混 了,这几天才弄明白它,于是在这里清理一下头脑。 一、 什么是ioctl。 ioctl是设备驱动程序中对设备的I/O通道进行管理的函数。所谓对I/O通道进行管理,就 是对设备的一些特性进行控制,例如串口的传输波特率、马达的转速等等。它的调用个数 如下: int ioctl(int fd, ind cmd, …); 其中fd就是用户程序打开设备时使用open函数返回的文件标示符,cmd就是用户程序对设 备的控制命令,至于后面的省略号,那是一些补充参数,一般最多一个,有或没有是和 cmd的意义相关的。 ioctl函数是文件结构中的一个属性分量,就是说如果你的驱动程序提供了对ioctl的支 持,用户就可以在用户程序中使用ioctl函数控制设备的I/O通道。 二、 ioctl的必要性 如果不用ioctl的话,也可以实现对设备I/O通道的控制,但那就是蛮拧了。例如,我们可 以在驱动程序中实现write的时候检查一下是否有特殊约定的数据流通过,如果有的话, 那么后面就跟着控制命令(一般在socket编程中常常这样做)。但是如果这样做的话,会 导致代码分工不明,程序结构混乱,程序员自己也会头昏眼花的。 所以,我们就使用ioctl来实现控制的功能。要记住,用户程序所作的只是通过命令码告 诉驱动程序它想做什么,至于怎么解释这些命令和怎么实现这些命令,这都是驱动程序要 做的事情。 三、 ioctl如何实现 这是一个很麻烦的问题,我是能省则省。要说清楚它,没有四五千字是不行的,所以我这 里是不可能把它说得非常清楚了,不过如果有读者对用户程序怎么和驱动程序联系起来感 兴趣的话,可以看我前一阵子写的《write的奥秘》。读者只要把write换成ioctl,就知 道用户程序的ioctl是怎么和驱动程序中的ioctl实现联系在一起的了。 我这里说一个大概思路,因为我觉得《Linux设备驱动程序》这本书已经说的非常清楚 了,但是得化一些时间来看。 在驱动程序中实现的ioctl函数体内,实际上是有一个switch{case}结构,每一个case对 应一个命令码,做出一些相应的操作。怎么实现这些操作,这是每一个程序员自己的事 情,因为设备都是特定的,这里也没法说。关键在于怎么样组织命令码,因为在ioctl中 命令码是唯一联系用户程序命令和驱动程序支持的途径。 命令码的组织是有一些讲究的,因为我们一定要做到命令和设备是一一对应的,这样才不 会将正确的命令发给错误的设备,或者是把错误的命令发给正确的设备,或者是把错误的 命令发给错误的设备。这些错误都会导致不可预料的事情发生,而当程序员发现了这些奇 怪的事情的时候,再来调试程序查找错误,那将是非常困难的事情。 所以在Linux核心中是这样定义一个命令码的: ____________________________________ | 设备类型 | 序列号 | 方向 |数据尺寸| |----------|--------|------|--------| | 8 bit | 8 bit |2 bit |8~14 bit| |----------|--------|------|--------| 这样一来,一个命令就变成了一个整数形式的命令码。但是命令码非常的不直观,所以 Linux Kernel中提供了一些宏,这些宏可根据便于理解的字符串生成命令码,或者是从 命令码得到一些用户可以理解的字符串以标明这个命令对应的设备类型、设备序列号、数 据传送方向和数据传输尺寸。 这些宏我就不在这里解释了,具体的形式请读者察看Linux核心源代码中的和,文件里给 除了这些宏完整的定义。这里我只多说一个地方,那就是"幻数"。 幻数是一个字母,数据长度也是8,所以就用一个特定的字母来标明设备类型,这和用一 个数字是一样的,只是更加利于记忆和理解。就是这样,再没有更复杂的了。 更多的说了也没有,读者还是看一看源代码吧,推荐各位阅读《Linux 设备驱动程序》所 带源代码中的short一例,因为它比较短小,功能比较简单,可以看明白ioctl的功能和细 节。 四、 cmd参数如何得出 这里确实要说一说,cmd参数在用户程序端由一些宏根据设备类型、序列号、传送方向、 数据尺寸等生成,这个整数通过系统调用传递到内核中的驱动程序,再由驱动程序使用解 码宏从这个整数中得到设备的类型、序列号、传送方向、数据尺寸等信息,然后通过 switch{case}结构进行相应的操作。 要透彻理解,只能是通过阅读源代码,我这篇文章实际上只是一个引子。Cmd参数的组织 还是比较复杂的,我认为要搞熟它还是得花不少时间的,但是这是值得的,驱动程序中最 难的是对中断的理解。 五、 小结 ioctl其实没有什么很难的东西需要理解,关键是理解cmd命令码是怎么在用户程序里生成 并在驱动程序里解析的,程序员最主要的工作量在switch{case}结构中,因为对设备的 I/O控制都是通过这一部分的代码实现的。 参考资料: 1.《Linux 设备驱动程序》,鲁宾尼著,中国电力出版社。 2.《write的奥秘》,coly,真情流露(202.204.7.235)->电脑技术->Linux技术。  

 
中国Linux论坛 版权所有



Copyright 1999,2000, 2001 China Linux Forum