EDN首页   博客首页

最新日志

发表于:2008-7-3 22:38:40
标签:无标签

0

14.9.2读取一个文件的属性

我们使用函数statfstatlstat来检查文件的属性。这些函数使用struct stat对象来返回属性信息。所有这三个函数声明在头文件‘sys/stat.h’中。

Int   stat(const char *filename, struct stat *buf)                              函数

Stat函数返回buf指向的结构体中filename项中保存的文件名的文件的属性信息。如果filename项是一个符号链接,你得到的是链接指向的文件的属性信息。如果链接指向一个不存在的文件,则stat函数会报告一个文件不存在的失败消息。

如果操作成功的话,该函数返回值为0,失败则返回-1。除了通常的文件名错误外,还定义有如下的errno出错条件。

ENOENT              filename命名的文件不存在

如果使用_FILE_OFFSET_BITS==64来编译时,该函数实际上是stat64,因此使用大型文件支持的接口代替普通的实现。

Int   stat64(const char *filename, struct stat64 *buf)                                     函数

此函数与函数stat类似,区别在于它能够在32位系统上处理大小大于231的文件。为了达到效果,结果保存在一个struct stat64类型的变量中,就是buf指针指向的变量。当源代码中使用_FILE_OFFSET_BITS==64来编译时,该函数在使用stat为函数名时也有效,当然在32位机器代替小文件的接口。

Int   fstat(int filedes,struct stat *buf)                                函数

Fstat函数与stat函数类似,只是在打开一个文件时使用文件描述符代替文件名做为参数。详情查看Chapter 13【低级输入输出】。像stat函数一样,fstat函数调用成功返回值为0,失败则返回-1。下述errno错误情况针对fstat定义的:

EBADF          filedes参数是一个无效的文件描述符。

如果使用_FILE_OFFSET_BITS==64来编译时,该函数实际上是stat64,因此使用大型文件支持的接口代替普通的实现。

Int   fstat64(int filedes, struct stat64 *buf)                        函数

此函数与函数fstat类似,区别在于它能够在32位系统上处理大小大于231的文件。因为大型文件的文件描述符一般通过open64或者creat64来获得。Buf指针指向的变量类型是struct stat64,用于代表大型文件。当源代码中使用_FILE_OFFSET_BITS==64来编译时,该函数在使用stat为函数名时也有效,当然在32位机器代替小文件的接口。

Int   lstat(const char *filename, struct stat *buf)                函数

Lstat函数与stat函数类似,区别在于lstat函数不对符号链接进行追踪。如果参数filename是一个符号链接名,lstat函数仅仅返回链接本身的信息。详情查看Section 14.5【符号链接】,否则lstat函数与stat函数作用相同。

如果使用_FILE_OFFSET_BITS==64来编译时,该函数实际上是stat64,因此使用大型文件支持的接口代替普通的实现。

Int   lstat64(const char *filename, struct stat64 *buf)         函数

此函数与函数stat类似,区别在于它能够在32位系统上处理大小大于231的文件。为了达到效果,结果保存在一个struct stat64类型的变量中,就是buf指针指向的变量。当源代码中使用_FILE_OFFSET_BITS==64来编译时,该函数在使用stat为函数名时也有效,当然在32位机器代替小文件的接口。

点击此处查看原文 >>

系统分类: 资源共享   |    用户分类:    |    来源: 原创

评论(0) | 阅读(162)
发表于:2008-7-2 22:59:07
标签:无标签

1

14.9.1文件属性的意义

14.9.1      文件属性的意义

当你读取一个文件的属性时,会返回一个struct stat结构体。本小节接下来解释文件属性的名字、属性的数据类型以及它们所代表的含义。读取文件属性的函数参照14.9.2小节。

头文件‘sys/stat.h’中声明了本小节中使用的所有的标志符:

Struct     stat                                                                               数据类型

Stat结构体返回关于文件属性的信息。该结构体至少包含以下数据成员:

Mode_t   st_mode

指定文件的模式,包括文件类型信息和文件权限位。

Ino_t       st_ino

文件序列号,用来区分与其它表示相同设备的文件。

Dev_t      st_dev

确定该设备包含的文件。St_inost_dev一起来唯一的确定一个文件。St_dev的值在重启或系统崩溃过程中不一定会保持一致。

Nlink_t    st_nlink

链接到文件的硬链接数目。该计数器记录有多少目录项链接到该文件,如果该计数器的值减位0时,因为没有进程打开该文件所以这个文件会被丢弃。符号链接不会计数。

Uid_t       st_uid

文件所有者的用户ID

Gid_t      st_gid

文件的组ID

Off_t      st_size

bytes来显示一个合法文件的大小。对于一个真实的设备文件该选项没有确定的意义。对于符号链接来说表示该链接指向的文件的长度。

Time_t    st_atime

表示最后访问该文件的时间

Unsigned long int    st_atime_usec

最后访问该文件时间的部分内容

Time_t    st_mtime

最后修改该文件内容的时间

Unsigned long int    st_mtime_usec

最后修改文件内容时间的部分内容

Time_t    st_ctime

最后修改文件属性的时间

Unsigned long int    st_ctime_usec

最后修改文件属性的时间的部分内容

Blkcnt_t  st_blocks

用于统计该文件占有的磁盘空间,用512byte的块来衡量。文件占有磁盘块的数量与文件的大小并不严格成比例有两个原因:文件系统可能使用一些块来保存内部记录;文件可能是稀疏的,该文件可能存在一些空洞,这些空洞不一定实际占有磁盘的空间。

你可以使用与st_size来比较大小的方法来确定一个文件是否存在空洞,如下所示:

st.st_blocks*512 < st.st_size)。当一个文件只有少量空洞的时候该测试在测试文件是否存在时不一定会起作用。对于实际应用来说,这个问题不会太大。

Unsigned int    st_blksize

在读写文件时采用的最佳块大小,用bytes为单位。你可能会使用这个数字来分配一个文件的读写缓冲区的大小。与st_blocks无关。

为了扩展对大型文件的支持,甚至在32位的机器上能够处理大小为263文件,因此关于struct stat的新的定义时必须的。

Struct stat64                                                                                数据类型

该类型的数据成员与struct stat的数据成员有相同的名字。唯一的区别就是st_ino,st_sizest_blocks的类型不同,因为要支持更大的数值。

Mode_t   st_mode

指定文件的模式,包括文件类型信息和文件权限位。

Ino64_t   st_ino

文件序列号,用来区分与其它表示相同设备的文件。

Dev_t      st_dev

确定该设备包含的文件。St_inost_dev一起来唯一的确定一个文件。St_dev的值在重启或系统崩溃过程中不一定会保持一致。

Nlink_t    st_nlink

链接到文件的硬链接数目。该计数器记录有多少目录项链接到该文件,如果该计数器的值减位0时,因为没有进程打开该文件所以这个文件会被丢弃。符号链接不会计数。

Uid_t       st_uid

文件所有者的用户ID

Gid_t      st_gid

文件的组ID

Off64_t   st_size

bytes来显示一个合法文件的大小。对于一个真实的设备文件该选项没有确定的意义。对于符号链接来说表示该链接指向的文件的长度。

Time_t    st_atime

表示最后访问该文件的时间

Unsigned long int    st_atime_usec

最后访问该文件时间的部分内容

Time_t    st_mtime

最后修改该文件内容的时间

Unsigned long int    st_mtime_usec

最后修改文件内容时间的部分内容

Time_t    st_ctime

最后修改文件属性的时间

Unsigned long int    st_ctime_usec

最后修改文件属性的时间的部分内容

Blkcnt64_t      st_blocks

用于统计该文件占有的磁盘空间,用512byte的块来衡量。文件占有磁盘块的数量与文件的大小并不严格成比例有两个原因:文件系统可能使用一些块来保存内部记录;文件可能是稀疏的,该文件可能存在一些空洞,这些空洞不一定实际占有磁盘的空间。

你可以使用与st_size来比较大小的方法来确定一个文件是否存在空洞,如下所示:

st.st_blocks*512 < st.st_size)。当一个文件只有少量空洞的时候该测试在测试文件是否存在时不一定会起作用。对于实际应用来说,这个问题不会太大。

Unsigned int    st_blksize

在读写文件时采用的最佳块大小,用bytes为单位。你可能会使用这个数字来分配一个文件的读写缓冲区的大小。与st_blocks无关。

有些文件属性使用一些特定的已存在的数据类型名来指定这些属性。这些都是众所周知的整型的别名。这些转定义类型名既在头文件‘sys/types.h’又在‘sys/stat.h’中定义。列表如下:

Mode_t

这是一个整型数据类型用来代表文件模式。在GNU系统中,与unsigned int具有相同的意义。

Ino_t

这是一个算术数据类型用来表示文件序列号。(在UNIX中有时称为inode数字)在GNU系统中,等同于unsigned long int。如果源代码使用_FILE_OFFSET_BITS==64来编译时,该类型则使用ino64_t代替。

Ino64_t

这是一个算术数据类型用来表示文件序列号用于支持大型文件。在GNU系统中,等同于unsigned long int。如果源代码使用_FILE_OFFSET_BITS==64来编译时,该类型在使用ino_t类型名的情况下同样有效。

Dev_t

这是一个算术数据类型用来表示文件设备号。在GNU系统中,等同于int

Nlink_t

这是一个算术数据类型用来表示文件链接数目。在GNU系统中,等同于unsigned short int

Blkcnt_t

这是一个算术数据类型用来表示数据块的数目。在GNU系统中等同于unsigned long int。如果使用_FILE_OFFSET_BITS==64来编译时,则使用blkcnt64_t代替。

Blkcnt64_t

这是一个算术数据类型用来表示文件序列号用于支持大型文件。在GNU系统中,等同于unsigned long long int。如果源代码使用_FILE_OFFSET_BITS==64来编译时,该类型在使用blkcnt64_t类型名的情况下同样有效。

点击此处查看原文 >>

系统分类: 资源共享   |    用户分类:    |    来源: 原创

评论(0) | 阅读(126)
发表于:2008-6-27 21:47:29
标签:无标签

1

安凯面试

    6月24号安凯公司人资打电话给我,只是当时在培训没有接到,当时心就凉了感觉没戏了。没想到25号,人资又打电话给我通知我26号去面试,安凯的人资很负责。

    26号下午坐车去面试,哪知早了两站下车,只得继续坐11路再去了,好事多磨啊。下午一点半到了安凯公司,公司前台的MM很养眼,态度也好。

    公司人资先是给我一份C语言的试题(四页),45分钟做完。看到试题才发现自己掌握的东西不够,那些不定项选择题总是看到很多东西都是是时而非只能凭感觉答题了。最后有两道程序设计题,我水平不够,只做了一道就时间到了。第一题是:判断一个单链表中是否存在循环链表。第二道题是:用栈实现单向链表的逆转。

    完了之后是一位项目负责人来面试,主要是相互之间聊聊。先是自我介绍,因为我是应聘测试的实习生,所以集中的有关测试的问题上。可是,之前对软件测试不了解,很多都是按自己感觉来回答的。接下来就是测试主管面试(是美女),先是让我做了两道测试的题。因为没有经验,那些题目只考虑到其中的一些情况,忽略了其它的很多情况。还好美女主管给了我一些建议,小小感动一番。最后到4点半整个面试才完成。这次是我遇到的面试中最为专业的,从人资到专业面试都很负责。

     纪念一下自己的面试之旅。

点击此处查看原文 >>

系统分类: 生活点滴   |    用户分类:    |    来源: 原创

评论(0) | 阅读(128)
发表于:2008-6-15 22:04:33
标签:无标签

1

翻译automake book9.1.5

这次翻译感觉很差,如果您有更好的翻译请寄一份我,谢谢!jiangray@126.com。希望大家互相交流,互相学习。

9.1.5 Fallback回退、回滚 Function Implementations

Due to the huge number of Unix varieties in common use today, many of the C library functions that you take for granted on your preferred development platform are very likely missing from some of the architectures you would like your code to compile on. Fundamentally there are two ways to cope with this:

Use only the few library calls that are available everywhere. In reality this is not actually possible because there are two lowest common denominators最小共同点 with mutually exclusive互斥的 APIs, one rooted in BSD Unix (`bcopy', `rindex') and the other in SYSV Unix (`memcpy', `strrchr'). The only way to deal with this is to define one API in terms of the other using the preprocessor. The newer POSIX standard deprecates反对 many of the BSD originated calls (with exceptions such as the BSD socket API). Even on non-POSIX platforms, there has been so much cross pollination that often both varieties of a given call may be provided, however you would be wise to write your code using POSIX endorsed calls, and where they are missing, define them in terms of whatever the host platform provides.

This approach requires a lot of knowledge about various system libraries and standards documents, and can leave you with reams of大量 preprocessor code to handle the differences between APIS. You will also need to perform a lot of checking in `configure.in' to figure out which calls are available. For example, to allow the rest of your code to use the `strcpy' call with impunity, you would need the following code in `configure.in':

AC_CHECK_FUNCS(strcpy bcopy)

And the following preprocessor code in a header file that is seen by every source file:

#if !HAVE_STRCPY

#  if HAVE_BCOPY

#    define strcpy(dest, src)   bcopy (src, dest, 1 + strlen (src))

#  else /* !HAVE_BCOPY */

     error no strcpy or bcopy

#  endif /* HAVE_BCOPY */

#endif /* HAVE_STRCPY */

Alternatively you could provide your own fallback implementations of function calls you know are missing on some platforms. In practice you don't need to be as knowledgeable博学的 about problematic有问题的 functions when using this approach. You can look in GNU libiberty(9) or Fran?ois Pinard's libit project(10) to see for which functions other GNU developers have needed to implement fallback code. The libit project is especially useful in this respect as it comprises由、、组成 canonical标准的 versions of fallback functions, and suitable Autoconf macros assembled from across the entire GNU project. I won't give an example of setting up your package to use this approach, since that is how I have chosen to structure the project described in this chapter.

Rather than writing code to the lowest common denominator of system libraries, I am a strong advocate拥护 of the latter school of thought思想派别 in the majority 占大多数of cases. As with all things it pays to take a pragmatic实用的 approach; don't be afraid of the middle ground -- weigh the options on a case by case basis.

由于目前有很多Unix版本正在使用之中,很多C库函数你认为在你选择的开发平台中是理所当然的事,然而很有可能在你编译代码的平台上就有可能没有这些库函数。有两个基本的方法用来处理这种情况:

尽可能在任何位置尽可能少的使用函数库调用。实际上,这种方法实用性不大,因为存在两组共同点小缺互相互斥的API,一组基于BSD Unix’bcopy’ ’rindex’,而另一组基于SYSV Unix(‘memcpy’‘strrchr’)。处理这个问题唯一的的方法就是根据其它的预处理器定义一个API。最新的POSIX标准不支持BSD原始的系统调用(BSD socket API除外)。甚至在非POSIX平台,存在如此多的cross pollination以至于所有的平台都可能提供一种系统调用的版本,所以你写的代码最好使用POSIX认可的系统调用,并且当这些系统调用不存在时,就自己定义这些系统调用。

这种方法需要了解各种系统函数库和有关各种标准的文档,并且这会使你需要大量的预处理代码来处理各种API之间的差异。你将来也需要在configure.in文件中做很多检测来确定哪些系统调用是可用的。举例来说,为了在后续代码中安全的使用‘strcpy’系统调用,在configure.in文件中需要添加如下代码:AC_CHECK_FUNCS(strcpy bcopy)

并且在所有的源文件可以看到下面的预处理代码出现在头文件中:

#if !HAVE_STRCPY

#  if HAVE_BCOPY

#    define strcpy(dest, src)   bcopy (src, dest, 1 + strlen (src))

#  else /* !HAVE_BCOPY */

     error no strcpy or bcopy

#  endif /* HAVE_BCOPY */

#endif /* HAVE_STRCPY */

另外一个方法就是当你知道在某些平台没有某些函数调用时,你自己实现关于函数调用的后退功能。实际上当你使用该方法时,你不需要详细了解那些有问题的函数。你可以查看GNU libiberty 或者Francois Pinards libit项目来看看哪个函数其它的GNU开发人员已经实现它的后退代码。由于libit项目由许多后退函数的标准版本组成,所以这个项目在这方面特别有效,并且合适的autoconf宏组合在整个GNU项目中。这里我不会给出在代码包中使用该方法的实例,因为这些在本章给出的项目中有相关的描述。

与其根据各系统函数库的最小共同点来写代码,不如使用后一种大家都使用的方法。对于所有的事情来说还是采用实用的的方法,就是具体情况具体分析。

 

点击此处查看原文 >>

系统分类: 资源共享   |    用户分类:    |    来源: 原创

评论(0) | 阅读(126)
发表于:2008-6-14 22:41:33
标签:无标签

2

翻译automake book9.1.3

9.1.3 C++ Compilers

In order for a C++ program to use a library compiled with a C compiler, it is necessary for any symbols exported from the C library to be declared between `extern "C" {' and `}'. This code is important, because a C++ compiler mangles(7)使变形 all variable and function names, where as a C compiler does not. On the other hand, a C compiler will not understand these lines, so you must be careful to make them invisible to the C compiler.

Sometimes you will see this method used, written out in long hand in every installed header file, like this:

#ifdef __cplusplus

extern "C" {

#endif

...

#ifdef __cplusplus

}

#endif

But that is a lot of unnecessary typing if you have a few dozen headers in your project. Also the additional braces tend to confuse text editors, such as emacs, which do automatic source indentation缩进 based on brace characters.

Far better, then, to declare them as macros in a common header file, and use the macros in your headers:

  #ifdef __cplusplus

#  define BEGIN_C_DECLS extern "C" {

#  define END_C_DECLS   }

#else /* !__cplusplus */

#  define BEGIN_C_DECLS

#  define END_C_DECLS

#endif /* __cplusplus */

I have seen several projects that name such macros with a leading underscore下划线 -- `_BEGIN_C_DECLS'. Any symbol with a leading underscore is reserved for use by the compiler implementation, so you shouldn't name any symbols of your own in this way. By way of example, I recently ported the Small(8) language compiler to Unix, and almost all of the work was writing a Perl script to rename huge numbers of symbols in the compiler's reserved保留的 namespace to something more sensible so that GCC could even parse分析 the sources. Small was originally developed on Windows, and the author had used a lot of symbols with a leading underscore. Although his symbol names didn't clash冲突、抵触 with his own compiler, in some cases they were the same as symbols used by GCC.

9.1.4 Function Definitions

As a stylistic风格 convention惯例, the return types for all function definitions should be on a separate line. The main reason for this is that it makes it very easy to find the functions in source file, by looking for a single identifier at the start of a line followed by an open parenthesis:

$ egrep '^[_a-zA-Z][_a-zA-Z0-9]*[ \t]*\(' error.c

set_program_name (const char *path)

error (int exit_status, const char *mode, const char *message)

sic_warning (const char *message)

sic_error (const char *message)

sic_fatal (const char *message)

There are emacs lisp functions and various code analysis tools, such as ansi2knr (see section 9.1.6 K&R Compilers), which rely on this formatting convention, too. Even if you don't use those tools yourself, your fellow developers might like to, so it is a good convention to adopt.

9.1.1          C++编译器

为了在C++程序中使用C语言的函数库,C函数库中的符号必须在`extern "C" {'`}之间声明。因为C++编译器会把所有的变量和函数名进行重命名,而C编译器不会这样做,所以上述这些代码非常重要。另一方面,由于C编译器是无法理解这些语句的,所以当使用C编译器编译时必须使这些语句失效。

有时你可以看到该方法应用在所有的头文件中,如下所示:

#ifdef __cplusplus

extern "C" {

#endif

...

#ifdef __cplusplus

}

#endif

如果你在你的项目中只使用了少量的头文件,则完全没有必要键入上述这些代码。而且多余的大括号还会造成文本编辑器(比如emacs)的混乱,因为emacs是基于大括号来对代码进行自动缩进的。

更好的方法是在一个普通的头文件中把这些代码声明为宏,并且在你的头文件中使用它们:

#ifdef __cplusplus

#  define BEGIN_C_DECLS extern "C" {

#  define END_C_DECLS   }

#else /* !__cplusplus */

#  define BEGIN_C_DECLS

#  define END_C_DECLS

#endif /* __cplusplus */

我发现很多项目在给这些宏命名的时候使用下划线,比如_BEGIN_C_DECLS。所有以下划线开头的符号都是预留给编译器编译程序时使用的,所有你在给自己的符号命名时不可以用下划线开头。顺便举个例子,最近我移植一个Small语言编译器到Unix环境下,大部分的工作都是编写Perl教本来给大量预留给编译器命名空间使用的符号重命名。起初,Small是在Windows环境下开发的,并且作者使用很多以下划线开头的符号。虽然他的那些符合与他的编译器不冲突,但是在一些地方他使用的符号与GCC预留的符号相同。

9.1.2          函数定义

有一个习惯的风格就是在定义函数时函数的返回类型放在单独的一行。这个做法的主要原因就是在源文件中通过一个在一行的开始后面紧跟着“(”的标志符来快速找到相应的函数:

$ egrep '^[_a-zA-Z][_a-zA-Z0-9]*[ \t]*\(' error.c

set_program_name (const char *path)

error (int exit_status, const char *mode, const char *message)

sic_warning (const char *message)

sic_error (const char *message)

sic_fatal (const char *message)

有一些emacs lisp函数和很多代码分析工具,比如ansi2knr,也是依靠这些格式习惯起作用。即使你自己不会用这些工具,但是你的继任开发人员有可能会用到,所以这是一个值得采纳的好习惯。

点击此处查看原文 >>

系统分类: 资源共享   |    用户分类:    |    来源: 原创