《UNIX环境高级编程》--6系统数据文件和信息

来源:本网整理

第1章 UNIX基础知识 11.1 引言 11.2 UNIX体系结构 11.3 11.4 文件和目录 31.5 输入和输出 61.6 程序和进程 81.7 出错处理 101.8 用户标识 121.9 信号 141.10 时间值 151.11 系统调用和库函数 161.12 小结 17习题 18第2章 UNIX标准化及实现 192.1 引言 192.2 UNIX标准化 192.2.1 ISO C 192.2.2 IEEE POSIX 202.2.3 Single UNIX Specification 252.2.4 FIPS 262.3 UNIX系统实现 262.3.1 SVR4 262.3.2 4.4BSD 272.3.3 FreeBSD 272.3.4 Linux 272.3.5 Mac OS X 282.3.6 Solaris 282.3.7 其他UNIX系统 282.4 标准和实现的关系 282.5 限制 292.5.1 ISO C限制 292.5.2 POSIX限制 302.5.3 XSI限制 322.5.4 sysconf、pathconf和fpathconf函数 322.5.5 不确定的运行时限制 382.6 选项 422.7 功能测试宏 442.8 基本系统数据类型 452.9 标准之间的冲突 452.10 小结 46习题 46第3章 文件I/O 473.1 引言 473.2 文件描述符 473.3 open函数 483.4 creat函数 493.5 close函数 503.6 lseek函数 503.7 read函数 533.8 write函数 543.9 I/O的效率 543.10 文件共享 563.11 原子操作 593.12 dup和dup2函数 603.13 sync、fsync和fdatasync函数 613.14 fcntl函数 623.15 ioctl函数 663.16/dev/fd 673.17 小结 68习题 68第4章 文件和目录 714.1 引言 714.2 stat、fstat和lstat函数 714.3 文件类型 724.4 设置用户ID和设置组ID 744.5 文件访问权限 754.6 新文件和目录的所有权 774.7 access函数 774.8 umask函数 794.9 chmod和fchmod函数 814.10 粘住位 834.11 chown、fchown和lchown函数 844.12 文件长度 854.13 文件截短 864.14 文件系统 864.15 link、unlink、remove和rename函数 894.16 符号链接 914.17 symlink和readlink函数 944.18 文件的时间 944.19 utime函数 954.20 mkdir和rmdir函数 974.21 读目录 984.22 chdir、fchdir和getcwd函数 1024.23 设备特殊文件 1044.24 文件访问权限位小结 1064.25 小结 106习题 107第5章 标准I/O库 1095.1 引言 1095.2 流和FILE对象 1095.3 标准输入、标准输出和标准出错 1105.4 缓冲 1105.5 打开流 1125.6 读和写流 1145.7 每次一行I/O 1165.8 标准I/O的效率 1175.9 二进制I/O 1195.10 定位流 1205.11 格式化I/O 1215.12 实现细节 1255.13 临时文件 1275.14 标准I/O的替代软件 1305.15 小结 130习题 130第6章 系统数据文件和信息 1336.1 引言 1336.2 口令文件 1336.3 阴影口令 1366.4 组文件 1376.5 附加组ID 1386.6 实现的区别 1396.7 其他数据文件 1396.8 登录账户记录 1406.9 系统标识 1416.10 时间和日期例程 1426.11 小结 146习题 146第7章 进程环境 1477.1 引言 1477.2 main函数 1477.3 进程终止 1477.4 命令行参数 1517.5 环境表 1527.6 C程序的存储空间布局 1527.7 共享库 1547.8 存储器分配 1547.9 环境变量 1577.10 setjmp和longjmp函数 1597.11 getrlimit和setrlimit函数 1647.12 小结 168习题 168第8章 进程控制 1718.1 引言 1718.2 进程标识符 1718.3 fork函数 1728.4 vfork函数 1768.5 exit函数 1788.6 wait和waitpid函数 1798.7 waitid函数 1838.8 wait3和wait4函数 1848.9 竞争条件 1858.10 exec函数 1888.11 更改用户ID和组ID 1928.12 解释器文件 1968.13 system函数 2008.14 进程会计 2038.15 用户标识 2088.16 进程时间 2088.17 小结 210习题 211第9章 进程关系 2139.1 引言 2139.2 终端登录 2139.3 网络登录 2169.4 进程组 2189.5 会话 2199.6 控制终端 2209.7 tcgetpgrp、tcsetpgrp和tcgetsid函数 2219.8 作业控制 2229.9 shell执行程序 2259.10 孤儿进程组 2289.11 FreeBSD实现 2309.12 小结 231习题 232第10章 信号 23310.1 引言 23310.2 信号概念 23310.3 signal函数 24010.4 不可靠的信号 24210.5 中断的系统调用 24410.6 可重入函数 24610.7 SIGCLD语义 24810.8 可靠信号术语和语义 25010.9 kill和raise函数 25110.10 alarm和pause函数 25210.11 信号集 25610.12 sigprocmask函数 25810.13 sigpending函数 25910.14 sigaction函数 26110.15 sigsetjmp和siglongjmp函数 26610.16 sigsuspend函数 26810.17 abort函数 27410.18 system函数 27610.19 sleep函数 28010.20 作业控制信号 28210.21 其他特征 28410.22 小结 285习题 285第11章 线程 28711.1 引言 28711.2 线程概念 28711.3 线程标识 28811.4 线程的创建 28811.5 线程终止 29111.6 线程同步 29711.7 小结 311习题 311第12章 线程控制 31312.1 引言 31312.2 线程限制 31312.3 线程属性 31412.4 同步属性 31812.5 重入 32412.6 线程私有数据 32812.7 取消选项 33112.8 线程和信号 33312.9 线程和fork 33612.10 线程和I/O 33912.11 小结 340习题 340第13章 守护进程 34113.1 引言 34113.2 守护进程的特征 34113.3 编程规则 34213.4 出错记录 34513.5 单实例守护进程 34813.6 守护进程的惯例 35013.7 客户进程-服务器进程模型 35413.8 小结 354习题 354第14章 高级I/O 35514.1 引言 35514.2 非阻塞I/O 35514.3 记录锁 35714.4 STREAMS 37014.5 I/O多路转接 37914.5.1 select和pselect函数 38114.5.2 poll函数 38414.6 异步I/O 38614.6.1 系统V异步I/O 38614.6.2 BSD异步I/O 38714.7 readv和writev函数 38714.8 readn和writen函数 38914.9 存储映射I/O 39014.10 小结 395习题 396第15章 进程间通信 39715.1 引言 39715.2 管道 39815.3 popen和pclose函数 40315.4 协同进程 40815.5 FIFO 41215.6 XSI IPC 41515.6.1 标识符和键 41515.6.2 权限结构 41615.6.3 结构限制 41715.6.4 优点和缺点 41715.7 消息队列 41815.8 信号量 42215.9 共享存储 42715.10 客户进程-服务器进程属性 43215.11 小结 434习题 434第16章 网络IPC:套接字 43716.1 引言 43716.2 套接字描述符 43716.3 寻址 43916.3.1 字节序 44016.3.2 地址格式 44116.3.3 地址查询 44216.3.4 将套接字与地址绑定 44916.4 建立连接 45016.5 数据传输 45216.6 套接字选项 46416.7 带外数据 46616.8 非阻塞和异步I/O 46716.9 小结 468习题 468第17章 高级进程间通信 46917.1 引言 46917.2 基于STREAMS的管道 46917.2.1 命名的STREAMS管道 47217.2.2 唯一连接 47317.3 UNIX域套接字 47617.3.1 命名UNIX域套接字 47717.3.2 唯一连接 47817.4 传送文件描述符 48217.4.1 经由基于STREAMS的管道传送文件描述符 48417.4.2 经由UNIX域套接字传送文件描述符 48617.5 open服务器版本1 49317.6 open服务器版本2 49817.7 小结 505习题 505第18章 终端I/O 50718.1 引言 50718.2 综述 50718.3 特殊输入字符 51218.4 获得和设置终端属性 51618.5 终端选项标志 51618.6 stty命令 52218.7 波特率函数 52318.8 行控制函数 52418.9 终端标识 52418.10 规范模式 52918.11 非规范模式 53218.12 终端的窗口大小 53718.13 termcap,terminfo和curses 53918.14 小结 540习题 540第19章 伪终端 54119.1 引言 54119.2 概述 54119.3 打开伪终端设备 54419.3.1 基于STREAMS的伪终端 54719.3.2 基于BSD的伪终端 54919.3.3 基于Linux的伪终端 55119.4 pty_fork函数 55319.5 pty程序 55519.6 使用pty程序 55919.7 高级特性 56419.8 小结 565习题 565第20章 数据库函数库 56720.1 引言 56720.2 历史 56720.3 函数库 56820.4 实现概述 56920.5 集中式或非集中式 57220.6 并发 57420.7 构造函数库 57420.8 源代码 57520.9 性能 59820.10 小结 600习题 601第21章 与网络打印机通信 60321.1 引言 60321.2 网络打印协议 60321.3 超文本传输协议 60521.4 打印假脱机技术 60521.5 源代码 60721.6 小结 644习题 645附录A 函数原型 647附录B 其他源代码 677附录C 部分习题答案 685参考书目 709索引 715www.zgxue.com防采集请勿采集本网。

系统数据文件和信息

用户配置文件

1. /etc/passwd

  1. UNIX口令文件 /etc/passwd/是一个ASCII文件,每一行包含很多字段,字段之间用冒号分隔。这些字段包含在<pwd.h>头文件定义的passwd,该结构有如下成员:

    • char *pw_name:用户名
    • char *pw_passwd:加密口令
    • uid_t pw_uid:数值用户ID
    • gid_t pw_gid:数值组ID
    • char *pw_gecos:注释字段
    • char *pw_dir:初始工作目录
    • char *pw_shell:初始shell
    • char *pw_class:用户访问类
    • time_t pw_change:下次更改口令时间
    • time_t pw_expire:账户有效期时间

    我在ubuntu下作java开发,有时候也有在windows下,上次在书店买了本unix高级环境编程书,随便翻翻看,感觉和JAVA不沾边。是应该继续看?还是以后再看,请不要复制了,认真帮我下巴,哥们,这是我

    关于口令文件:

    • 通常有一个用户名为root的登录项,其用户ID是 0
    • 加密口令字段包含一个占位符。现在加密口令其实是放在/etc/shadow
    • 口令文件中某些字段可能为空。

      你用JAVA的话就不用学搞unix高级环境编程了。你需要做的只是不断地深入了解JAVA的运行平台。她位于操作系统之上。至于Windows,Unix,懂就行了,不需要深入。除非你学的是C语言。C++。那就得搞

      • 如果加密口令字段为空,则说明该用户没有口令,没有口令则不能登录
    • shell字段指定了初始shell

      前两张应该是 Chapter 1.UNIX System Overview Chapter 2.UNIX Standardization and Implementations 主要是 unix 操作系统的简单介绍和标准化的相关问题,和编程没有直接关系,如果你从来没用过

      • 若它为空,则取系统默认值(通常是/bin/sh)linux下为/bin/bash
      • 若它为/dev/null,则会阻止任何人以该字段所在行记录中的用户名来登录系统
    • 用户名如果是nobody,则任何人都可以使用它登录系统,但是其用户ID和组ID不提供任何特权。该用户ID和组ID只能访问人人皆可读、可写的文件
    • Linux中,没有 pw_class,pw_change,pw_expire字段

注意如果要将一个用户设为不能登录

现在学的都是linux了。学完linux你可以学嵌入式,偏硬件一点。学习软件的话,可以学安卓。

1.可以将其shell设为/bin/false/bin/true

Unix环境高级编程?Unix的环境跟Linux很接近,但Linux免费,Unix是商用的。所以你可以从熟悉Linux下手,先熟悉系统的各项功能,命令行的使用,熟悉VI Gedit等文本编辑软件的使用,再进一步到

2.可以在/etc/shadow下将密码字段前加!!*

  1. getpwuid/getpwnam函数:读取口令文件:

    #include<pwd.h>struct passwd* getpwuid(uid_t uid);struct passwd* getpwnam(const char*name);

    • 参数:

      • uid:用户ID
      • name:用户名
    • 返回值:

      • 成功:返回passwd结构的指针
      • 失败:返回NULL

    注意:getpwuid/getpwnam函数返回的 struct passwd结构通常是函数内部的静态变量,因此多次调用上面的函数,该静态变量会被覆写。

  2. 查看整个口令文件,使用下面的函数:

    #include<pwd.h>struct passwd *getpwent(void);void setpwent(void);void endpwent(void);

    • getpwent返回值:

      • 成功:返回passwd结构的指针
      • 失败:返回NULL
      • 到达文件尾端:返回NULL

    用法:

    • 调用getpwent时,它返回口令文件中的下一个记录项

    返回的 struct passwd结构通常是函数内部的静态变量,因此多次调用getpwent函数,该静态变量会被覆写

  3. 在第一次调用getpwent函数时,它会打开所使用的各个文件
  4. getpwent对返回的各个记录项顺序并没有要求
  5. setpwent会反绕getpwent所使用的文件到文件起始处。即当调用setpwent之后,getpwent又会从头开始读取记录项
  6. endpwent会关闭getpwent所使用的文件。在调用getpwent读取完口令文件后,一定要调用endpwent关闭这些文件

    getpwent知道什么时候应该打开它所使用的文件(第一次被调用时),但是不知道何时应该关闭这些文件

  7. 加密口令是经单向加密算法处理过的用户口令副本。

    因为此算法是单向的,所以不能从加密口令猜测到原始口令

    现在的UNIX将加密口令存放在一个称作阴影口令的文件中(即文件/etc/shadow)。该文件至少应该包含用户名和加密口令。这些字段包含在<shadow.h>头文件的struct spwd结构中。相关的字段如下:

    • char *sp_namp:用户登录名
    • char *sp_pwdp:加密口令
    • int sp_lstchg:上次更改口令以来经过的时间
    • int sp_min:经过多少天后允许修改口令
    • int sp_max:经过多少天后必须修改口令
    • int sp_warn:经过多少天后如果未修改口令则系统发出警告
    • int sp_inact:经过多少天后,该账户是inactive
    • int sp_expire:经过多少天后,该账户过期
    • unsigned int sp_flag:保留字段

    其中只有用户登录名和加密口令这两个字段是必须的。其他字段都是用于控制口令更改的频率。

    注意:

    • 阴影口令文件/etc/shadow 不应该由一般用户读取。

      • 仅有少数几个程序需要访问加密口令,如login,passwd。这些程序通常是设置用户ID为root的程序
      • 普通口令文件/etc/passwd/可以任由各用户读取
  8. 用于读取阴影口令文件的函数为:

    #include<shadow.h>struct spwd *getspnam(const char*name);struct spwd *getspent(void);void setspent(void);void endspent(void);

    • getspnam参数:

      • name:用户名
    • getspnam返回值:

      • 成功:返回spwd结构指针
      • 失败:返回NULL
    • getspent返回值:

      • 成功:返回spwd结构指针
      • 失败:返回NULL
      • 到达文件尾端:返回NULL

    用法:

    • 调用 getspnam时,它返回阴影口令文件中,对应用户名的那一条记录项

    返回的 struct spwd结构通常是函数内部的静态变量,因此多次调用getspnam函数,该静态变量会被覆写

  9. 调用getspent时,它返回阴影口令文件中的下一个记录项

    返回的 struct spwd结构通常是函数内部的静态变量,因此多次调用getspent函数,该静态变量会被覆写

  10. 在第一次调用getspent函数时,它会打开所使用的各个文件
  11. getspent对返回的各个记录项顺序并没有要求
  12. setspent会反绕getspent所使用的文件到文件起始处。即当调用setspent之后,getspent又会从头开始读取记录项
  13. endspent会关闭getspent所使用的文件。在调用getspent读取完阴影口令文件后,一定要调用endspent关闭这些文件

    getspent知道什么时候应该打开它所使用的文件(第一次被调用时),但是不知道何时应该关闭这些文件

  14. UNIX 组文件包含的字段定义在<grp.h>所定义的group结构中:

    • char *gr_name:组名
    • char *gr_passwd:加密口令
    • int gr_gid:组ID
    • char **gr_mem:指向各用户名指针的数组

    它是一个指针数组,其中每个指针指向一个属于该组的用户名。该数组以null指针结尾

  15. struct_group

  16. getgrgid/getgrnam函数:查看组文件:

    #include<grp.h>struct group* getgrgid(gid_t gid);struct group* getgrnam(const char* name);

    • 参数:

      • gid:组ID
      • name:组名
    • 返回值:

      • 成功:返回group结构的指针
      • 失败:返回NULL

    注意:getgrgid/getgrnam函数返回的 struct group结构通常是函数内部的静态变量,因此多次调用上面的函数,该静态变量会被覆写。

  17. 查看整个组文件,使用下面的函数:

    #include<grp.h>struct group *getgrent(void);void setgrent(void);void endgrent(void);

    • getgrent返回值:

      • 成功:返回group结构的指针
      • 失败:返回NULL
      • 到达文件尾端:返回NULL

    用法:

    • 调用getgrent时,它返回组文件中的下一个记录项

    返回的 struct group结构通常是函数内部的静态变量,因此多次调用getgrent函数,该静态变量会被覆写

  18. 在第一次调用getgrent函数时,它会打开所使用的各个文件
  19. getgrent对返回的各个记录项顺序并没有要求
  20. setgrent会反绕getgrent所使用的文件到文件起始处。即当调用setgrent之后,getgrent又会从头开始读取记录项
  21. endgrent会关闭getgrent所使用的文件。在调用getgrent读取完组文件后,一定要调用endgrent关闭这些文件

    getgrent知道什么时候应该打开它所使用的文件(第一次被调用时),但是不知道何时应该关闭这些文件

  22. UNIX中还提供了附属组ID。其中获取和设置附属组ID的函数为:

    #include<unistd.h>int getgroups(int gidsetsize,gid_t grouplist[]);#include<grp.h> //对Linux#include<unistd.h> //对 FreeBSD, Mac OS X, Solarisint setgroups(int ngroups,const gid_t grouplist[]);#include<grp.h> //对Linux#include<unistd.h> //对 FreeBSD, Mac OS X, Solarisint initgroups(const char *username, gid_t basegid);

    参数:

    • 对于getgroups函数:

      • gidsetsize:填入grouplist数组的附属组ID的最大数量

        若该值为0,则函数只返回附属组ID数,而不修改grouplist数组

      • grouplist:存放附属组ID的数组
    • 对于setgroups函数:

      • ngroupsgrouplist数组中元素个数

        数量不能太大,不能超过NGROUPS_MAX

      • grouplist:待设置的附属组ID的数组
    • 对于initgroups函数:

      • username:用户名
      • basegid:用户的base组ID(它就是在口令文件中,用户名对于的组ID)

    返回值:

    • 对于getgroups函数:

      • 成功:返回附属组ID的数量
      • 失败:返回 -1
    • 对于setgroups/initgroups函数:

      • 成功:返回 0
      • 失败:返回 -1

    用法:

    • getgroups函数将进程所属用户的各附属组ID填写到grouplist中,填入该数组的附属组ID数最多为gidsetsize个。实际填写到数组中的附属组ID数由函数返回
    • setgroups函数可由超级用户调用以便为调用进程设置附属组ID表。
    • 由于initgroups函数会在内部调用setgroups函数,因此它也必须由超级用户调用
  23. 除了口令文件和组文件之外,系统中还有很多其他重要的数据文件。UNIX对于这些系统数据文件提供了对应的类似的API。对于每种数据文件,至少有三个函数:

    • get函数:读下一个记录。如果需要还会打开该文件。

      • 此种函数通常返回一个指向某个结构的指针。
      • 当已到达文件尾端时,返回空指针
      • 大多数get函数返回指向一个静态存储类结构的指针,如果需要保存其内容,则需要复制该结构
    • set函数:打开相应数据文件(如果尚未打开),然后反绕该文件

      • 如果希望在相应文件起始处开始处理,则调用该函数
    • end函数:关闭相应数据文件。在结束了对相应数据文件的读、写操作后,总应该调用此函数以关闭所有相关文件

    另外如果数据文件支持某种形式的键搜索,则也提供搜索具有指定键的记录的函数

    下面是各个重要的数据文件:

    说明 数据文件 头文件 结构 附加的键搜索函数
    口令 /etc/passwd passwd getpwnam,getpwuid
    /etc/group group getgrnam,getgrgid
    阴影 /etc/shadow

时间和日期

  1. UNIX内核提供的基本时间服务是自 UTC 1970-01-01 00:00:00 这一特定时间以来经过的秒数。

    • 这个时间称作日历时间,用数据类型 time_t 表示(它包括了时间和日期)
    • UNIX 提供若干个时间函数来转换日历时间
  2. time函数:返回当前的日历时间

    #include<time.h>time_t time(time_t *calptr);

    • 参数:

      • calptr:如果该指针不是NULL,则返回的日历时间也存放在calptr指向的内存中
    • 返回值:

      • 成功:返回当前日历时间的值
      • 失败:返回 -1
  3. clock_gettime函数:用于获取指定的时钟类型的时间:

    #include<sys/time.h>int clock_gettime(clockid_t clock_id,struct timespec *tsp);

    • 参数:

      • clock_id:时钟类型。

        • CLOCK_REALTIME:获取实时系统时间。此时clock_gettime函数提供了与time函数类似的功能。不过在系统支持高精度时间值的情况下,clock_gettime可能比time函数得到更高精度的时间值。
        • CLOCK_MONOTONIC:获取不带负跳数的实时系统时间
        • CLOCK_PROCESS_CPUTIME_ID:调用进程的CPU时间
        • CLOCK_THREAD_CPUTIME_ID:调用线程的CPU时间
      • tsp:存放获取时间的timespec结构(它把时间表示为秒和纳秒)的指针
    • 返回值:

      • 成功: 返回 0
      • 失败: 返回 -1
  4. clock_getres函数:时间精度调整

    #include<sys/time.h>int clock_getres(clockid_t clock_id,struct timespec *tsp);

    • 参数:

      • clock_id:时钟类型。
      • tsp:存放时间的timespec结构(它把时间表示为秒和纳秒)的指针
    • 返回值:

      • 成功: 返回 0
      • 失败: 返回 -1

    clock_getres函数把参数tsp指向的timespec结构初始化为与clock_id参数对应的始终精度

  5. clock_settime函数:设置时间

    #include<sys/time.h>int clock_settime(clockid_t clock_id,const struct timepsec *tsp);

    • 参数:

      • clock_id:时钟类型。
      • tsp:存放时间的timespec结构(它把时间表示为秒和纳秒)的指针
    • 返回值:

      • 成功: 返回 0
      • 失败: 返回 -1

    clock_settime函数对特定的时钟设置时间。但是:

    • 某些始终是不能修改的
    • 需要适当的权限来修改时钟值
  6. gettimeofday函数:更高精度的获取当前时间(但是目前已经弃用)

    #include<sys/time.h>int gettimeofday(struct timeval *restrict tp,void *restrict tzp);

    • 参数:

      • tp:存放当前时间的timeval结构(将当前时间表示为秒和微秒)的指针
      • tzp:唯一合法值是NULL。其他任何值都产生未定义的结果
    • 返回值:总是返回 0
  7. gmtime/localtime函数:将日历时间转换成struct tm结构:

    #include<time.h>struct tm* gmtime(const time_t *calptr);struct tm* localtime(const time_t *calptr);

    • 参数:calptr:指向日历时间的指针
    • 返回值:

      • 成功:指向struct tm结构的指针
      • 失败:返回NULL

    struct tm{ int tm_sec; //秒数,范围是 [0~60] int tm_min; //分钟数,范围是 [0~59] int tm_hour; //小时数,范围是 [0~23]。午夜12点是 0 int tm_mday; //一个月中的天数,范围是 [1~31] int tm_mon; //月数,范围是 [0~11] ,一月是 0 int tm_year; //年数,范围是 [1900~],如果是16则表示 1916 int tm_wday; //一个星期中的天数,范围是 [0~6] ,周日是0 int tm_yday; //一年中的天数,范围是 [0~365],一月一号是 0 int tm_isdst; //daylight saving time flag}

    其中秒可以超过 59 的理由是表示润秒

    gmtime/localtime函数的区别:

    • gmtime:将日历时间转换成统一协调的年月日时分秒周日分解结构
    • localtime:将日历时间转换成本地实际(考虑本地市区和夏令时标志),由TZ环境变量指定

    TZ环境变量影响localtime/mktime/strftime这三个函数:

    • 如果定义了TZ环境变量:则这些函数将使用TZ的值代替系统默认时区

    • 如果TZ定位为空TZ=,则使用UTC作为时区
  8. mktime函数:以本地时间的年月日等作为参数,将其变化成time_t值:

    #include<time.h>time_t mktime(struct tm*tmptr);

    • 参数: tmptr:指向struct tm结构的指针
    • 返回值:

      • 成功: 返回日历时间
      • 失败: 返回 -1

    所谓的本地实际的”本地“:由 TZ环境变量指定

  9. strftime/strftime_l函数:类似printf的打印时间的函数。它们可以通过可用的多个参数来定制产生的字符串

    #include<time.h>size_t strftime(char *restrict buf,size_t maxsize,const char*restrict format, const struct tm* restrict tmptr);size_t strftime_l(char *restrict buf,size_t maxsize,const char*restrict format, const struct tm* restrict tmptr,locale_t locale);

    • 参数:

      • buf:存放格式化后的时间字符串的缓冲区的地址
      • maxsize:存放格式化后的时间字符串的缓冲区的大小
      • format:时间的格式化字符串
      • tmptr:存放时间的struct tm结构的指针

      对于strftime_l 函数:

      • locale:指定的区域
    • 返回值:

      • 成功:返回存入buf的字符数
      • 失败: 返回 0

    注意:

    • 如果buf长度足够存放格式化结果以及一个null终止符,则这两个函数才有可能顺利转换;否则空间不够,这两个函数返回0,表示转换失败
    • strftime_l运行调用者将区域指定为参数;而strftime使用通过TZ环境变量指定的区域
    • format参数控制时间值的格式。如同printf,转换说明的形式是百分号之后跟随一个特定的字符,而format中的其他字符则按照原样输出:

      • %a:缩写的周日名,如Thu
      • %A:周日名,如Thursday
      • %b:缩写的月名:如Jan
      • %B:全月名,如January
      • %c:日期和时间,如Thu Jan 19 21:24:25 2012
      • %C:年的最后两位,范围是(00~99),如20
      • %d:月日,范围是 (01~31),如19
      • %D日期(MM/DD/YY),如01/19/12
      • %e月日(一位数字前加空格)(1~31),如19
      • %F:ISO 8601 日期格式 (YYYY-MM-DD),如 2012-01-19
      • %g:ISO 8601 年的最后2位数(00~99),如12
      • %G:ISO 8601 的年,如 2012
      • %h:与 %b 相同,缩写的月名
      • %H:小时(24小时制)(00~23)
      • %I:小时(12小时制)(01~12)
      • %j:年日(001~366),如019
      • %m:月(01~12),如 01
      • %M:分(00~59),如 24
      • %n:换行符
      • %pAM/PM
      • %r:本地时间(12小时制),如 09:24:52 PM
      • %R:与 %H:%M相同
      • %S:秒(00~60),如 52
      • %t:水平制表符
      • %T:同 %H:%M:%S 相同,如 21:24:52
      • %u:ISO 8601 周几(1~7,1为周一)
      • %U:一年的星期日周数(00~53)
      • %V:ISO 8601 周数(01~53)
      • %w:周几:(0~6,周日为0)
      • %W:一年的星期一周数(00~53)
      • %x:本地日期,如 01/19/12
      • %X:本地时间,如21:24:52
      • %y:年的最后两位(00~99)
      • %Y:年,如2012
      • %z:ISO 8601 格式的UTC偏移量,如 -0500
      • %Z:时区名,如EST
      • %%:百分号
  10. strptime函数:它是strftime的逆向过程,把时间字符串转换成struct tm时间

    #include<time.h>char *strptime(const char*restrict buf,const char*restrict format, struct tm*restrict tmptr);

    • 参数:

      • buf:存放已经格式化的时间字符串的缓冲区的地址
      • format:给出了buf缓冲区中的格式化时间字符串的格式
      • tmptr:存放时间的struct tm结构的指针
    • 返回值:

      • 成功:返回非NULL
      • 失败:返回NULL

    注意:strptime的格式化说明与strftime的几乎相同,但是下列会有区别

    • %a:缩写或者完整的周日名
    • %A:同%a
    • %b:缩写或者完整的月名
    • %B:同%b
    • %n:任何空白
    • %t:任何空白
$(function () { $('pre.prettyprint code').each(function () { var lines = $(this).text().split('\n').length; var $numbering = $('
    ').addClass('pre-numbering').hide(); $(this).addClass('has-numbering').parent().append($numbering); for (i = 1; i <= lines; i++) { $numbering.append($('
  • ').text(i)); }; $numbering.fadeIn(1700); }); });

    本文转载自taoyanqi8932博客,版权归taoyanqi8932所有

    ubuntu是可以的。编译环境的话装好ubuntu之后就自带了,你可以打开终端输入gcc-v就知道你的编译器版本了。还有你可能需要装其他的库文件。那本书的话建议你在没有了解linux系统的时候,最好从基础开始学起,不管怎么说,里面需要熟悉很多linux的命令,尽管他的名字是《UNIX环境高级编程》,但是他在序言里面说了,第二版的书涉及linux。你最好还是去了解一下系统的命令怎么用,然后再去学习内容来自www.zgxue.com请勿采集。

免责声明 - 关于我们 - 联系我们 - 广告联系 - 友情链接 - 帮助中心 - 频道导航
Copyright © 2017 www.zgxue.com All Rights Reserved