HICK 者,乡巴佬也

Linux 环境2(Beginning Linux Programming 笔记9)

Posted in: Linux 编程 — Hick @ 2009/06/13 14:33:59

p181 时间和日期

linux 下时间一般用 long int 型的类型 time_t ,其定义在 time.h 中,我们å¯ä»¥é€šè¿‡ time 函数获得 UNIX 时间戳值,原型以åŠå®žä¾‹å¦‚下:

// 原型
#include <time.h>
time_t time(time_t *tloc);
// 实例
#include <time.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int main()
{
    int i;
    time_t the_time;

    for(i = 1; i <= 10; i++) {
        the_time = time((time_t *)0);
        printf("The time is %ld\n", the_time);
        sleep(2);
    }
    exit(0);
}

è¯¥å‡½æ•°è¿”å›žæ—¶é—´æˆ³ï¼ŒåŒæ—¶æŠŠæ—¶é—´æˆ³ä¿å­˜å­— tlog ä¸­ã€‚æ³¨æ„ (time_t *)0 为 null 指针的写法。

p183 difftime 函数用æ¥è®¡ç®—时间差。gmtime åˆ™ç”¨æ¥æŠŠæ—¶é—´æˆ³è¾“å‡ºæˆåŒ…å«å¯è¯»æ—¶é—´çš„ tm 结构体:

#include <time.h>
#include <stdio.h>
#include <stdlib.h>

int main()
{
    struct tm *tm_ptr;
    time_t the_time;

    (void) time(&the_time);
    tm_ptr = gmtime(&the_time);

    printf("Raw time is %ld\n", the_time);
    printf("gmtime gives:\n");
    printf("date: %02d/%02d/%02d\n",
        tm_ptr->tm_year, tm_ptr->tm_mon+1, tm_ptr->tm_mday);
    printf("time: %02d:%02d:%02d\n",
        tm_ptr->tm_hour, tm_ptr->tm_min, tm_ptr->tm_sec);
    exit(0);
}

p184 gmtime 得到的是 GMT æ ‡å‡†æ—¶é—´ï¼Œè¦æƒ³å¾—到本地(本时区)时间,需è¦ç”¨ localtime 函数,它跟 gmtime 的区别åªåœ¨è¾“出ä¸åŒæ—¶åŒºçš„æ—¶é—´ã€‚

tm 结构体å¯ä»¥ç”± mkdir 函数转æ¢å›žæ—¶é—´æˆ³ï¼Œè½¬æ¢å¤±è´¥å‡½æ•°è¿”回 -1 :

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

å¦å¤– asctime 函数å¯ä»¥æŠŠ tm ç»“æž„è½¬æ¢æˆ”Sun Jun 9 12:34:56 2007\n\0″这样的字符串。 ctime 则相当于下é¢çš„第四行代ç ï¼š

#include <time.h>
char *asctime(const struct tm *timeptr);
char *ctime(const time_t *timeval);
asctime(localtime(timeval));

p186 strftime ç”¨æ¥æ ¼å¼åŒ–输出自定义的å¯è¯»çš„æ—¶é—´æ ¼å¼ã€‚

#include <time.h>
size_t strftime(char *s, size_t maxsize, const char *format, struct tm *timeptr);

把 timeptr 表示的 tm ç»“æž„ä½“æ—¶é—´è½¬åŒ–æˆ format 指定格å¼çš„字符串,date 命令对应的输出为: “%a %b %d %H:%M:%S %Yâ€ã€‚ å¦å¤– strptime 功能类似:

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

使用例å­ï¼š

#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
    struct tm *tm_ptr, timestruct;
    time_t the_time;
    char buf[256];
    char *result;

    (void) time(&the_time);
    tm_ptr = localtime(&the_time);
    strftime(buf, 256, "%A %d %B, %I:%S %p", tm_ptr);

    printf("strftime gives: %s\n", buf);

    strcpy(buf,"Thu 26 July 2007, 17:53 will do fine");

    printf("calling strptime with: %s\n", buf);
    tm_ptr = &timestruct;

    result = strptime(buf,"%a %d %b %Y, %R", tm_ptr);
    printf("strptime consumed up to: %s\n", result);

    printf("strptime gives:\n");
    printf("date: %02d/%02d/%02d\n",
        tm_ptr->tm_year % 100, tm_ptr->tm_mon+1, tm_ptr->tm_mday);
    printf("time: %02d:%02d\n",
        tm_ptr->tm_hour, tm_ptr->tm_min);
    exit(0);
}

p189 临时文件

tmpnam 函数å¯ä»¥ç”¨æ¥ç”Ÿæˆå”¯ä¸€æ–‡ä»¶å(文件系统中ä¸å­˜åœ¨çš„æ–‡ä»¶),åŒä¸€ä¸ªè¿›ç¨‹ä¸­å®ƒå¯ä»¥è¢«è°ƒç”¨ TMP_MAX æ¬¡ã€‚å‚æ•°éž null 时,生æˆçš„æ–‡ä»¶å会赋予给该å˜é‡ï¼š

#include <stdio.h>
char *tmpnam(char *s);

å¦‚æžœç”Ÿæˆæ–‡ä»¶å以åŽé©¬ä¸Šå°±éœ€è¦åˆ›å»ºæ–‡ä»¶ï¼Œå¯ä»¥ç›´æŽ¥ä½¿ç”¨ tmpfile å‡½æ•°ï¼Œè¿™æ ·èƒ½é˜²æ­¢åœ¨ç”Ÿæˆæ–‡ä»¶å到创建文件的过程中,å¦å¤–ä¸€ä¸ªè¿›ç¨‹åˆ›å»ºäº†åŒæ ·çš„æ–‡ä»¶ã€‚

#include <stdio.h>
FILE *tmpfile(void);

该函数返回指å‘ä¸´æ—¶æ–‡ä»¶çš„æ–‡ä»¶æµæŒ‡é’ˆï¼Œå¹¶ä¸”ä»¥è¯»å†™æ–¹å¼æ‰“开文件,当所有指å‘该文件的引用被关闭时,临时文件会被自动删除。注æ„因为有上é¢è¯´åˆ°çš„风险,所以一般创建临时文件都用 tmpfile æ¥ï¼Œå®žé™…上 GNU C 编译器会对 tmpname çš„ä½¿ç”¨äº§ç”Ÿä¸€æ¡ warning 。å¦å¤–,æŸäº› UNIX 版本中æä¾›å¦å¤–ä¸€ç§æ–¹å¼:

#include <stdlib.h>
char *mktemp(char *template);
int mkstemp(char *template);

p191 用户信æ¯

linux 中,除了 init 进程以外,所有的进程都是由用户或者其他进程å¯åŠ¨çš„ã€‚è¿›ç¨‹å¯åЍ以åŽï¼Œéƒ½ä¼šæœ‰ä¸€ä¸ªä¸Žä¹‹æƒ³å…³è”的用户,程åºä¸­ä»¥ç”¨æˆ·çš„唯一标识 UID æ¥è¡¨ç¤ºã€‚(su 命令å¯ä»¥æ”¹å˜è¿›ç¨‹çš„å¯åŠ¨ç”¨æˆ·) 。 UID 的结构体为 sys/types.h 中定义的 uid_t ,一般是个整型,éžç³»ç»Ÿè¿›ç¨‹ä¹Ÿå°±æ˜¯ç”¨æˆ·è¿›ç¨‹çš„ UID 一般大于 100 , init 进程为系统åˆå§‹è¿›ç¨‹ï¼Œ UID 为 0 。å¯ä»¥é€šè¿‡ä¸‹é¢çš„函数获得进程的 UID 或者用户å:

#include <sys/types.h>
#include <unistd.h>
uid_t getuid(void);
char *getlogin(void);

系统文件 /etc/passwd 中ä¿å­˜ç€ç³»ç»Ÿç”¨æˆ·çš„ä¿¡æ¯ï¼Œæ¯è¡Œä¸ºä¸€ä¸ªç”¨æˆ·çš„ä¿¡æ¯: 用户å:加密密ç :UID:GID/å…¨å:HOME目录:默认shell ,比如:

neil:zBqxfqedfpk:500:100:Neil Matthew:/home/neil:/bin/bash

现在的大多数系统中已ç»ä¸å†æŠŠå¯†ç åР坆䏲ä¿å­˜åœ¨è¿™é‡Œï¼Œè€Œæ˜¯ä½¿ç”¨”å½±å­å¯†ç (shadow password)”文件,一般在 /etc/shadow ,通过é™åˆ¶å¯¹å®ƒçš„æ“ä½œï¼Œæ¥åŠ å¼ºç³»ç»Ÿçš„å®‰å…¨æ€§ã€‚

我们å¯ä»¥é€šè¿‡ä¸‹é¢çš„函数获得用户的信æ¯:

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

getpwuid æ ¹æ® UID 返回 passwd 结构, getpwnam 则是通过用户å返回 passwd 结构,跟 /etc/passwd 文件对应,该结构包å«ä»¥ä¸‹æˆå‘˜ï¼š

. char *pw_name 用户å
. uid_t pw_uid UID
. gid_t pw_gid GID - group id
. char *pw_dir HOME 目录
. char *pw_gecos 用户全å
. char *pw_shell 用户默认 shell

注æ„获å–用户全å在ä¸åŒç³»ç»Ÿä¸‹å¯èƒ½å®šä¹‰ä¸ä¸€æ ·ï¼Œä¸Šé¢æ˜¯ linux 下的定义,其他系统å¯èƒ½æ˜¯ pw_comment ã€‚ä¸‹é¢æ˜¯ä¸€ä¸ªä½¿ç”¨ç¤ºèŒƒ:

#include <sys/types.h>
#include <pwd.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int main()
{
    uid_t uid;
    gid_t gid;
    struct passwd *pw;

    uid = getuid();
    gid = getgid();

    printf("User is %s\n", getlogin());

    printf("User IDs: uid=%d, gid=%d\n", uid, gid);

    pw = getpwuid(uid);
    printf("UID passwd entry:\n name=%s, uid=%d, gid=%d, home=%s, shell=%s\n",
        pw->pw_name, pw->pw_uid, pw->pw_gid, pw->pw_dir, pw->pw_shell);

    pw = getpwnam("root");
    printf("root passwd entry:\n");
    printf("name=%s, uid=%d, gid=%d, home=%s, shell=%s\n",
        pw->pw_name, pw->pw_uid, pw->pw_gid, pw->pw_dir, pw->pw_shell);
    exit(0);
}

如果需è¦é历所有用户信æ¯ï¼Œå¯ä»¥é€šè¿‡ getpwent 函数æ¥å®žçŽ°ï¼Œä¸è¯¦è¿°ã€‚

p194 获得主机信æ¯

如果一个 linux 机器在网络环境下,å¯ä»¥ä½¿ç”¨ gethostname 函数获得主机å,而用 uname å¯ä»¥èŽ·å¾—æ›´å¤šçš„ä¸»æœºä¿¡æ¯ï¼ŒåŒ…括æ“作系统以åŠéƒ¨åˆ†ç¡¬ä»¶ä¿¡æ¯ã€‚

#include <unistd.h>
int gethostname(char *name, size_t namelen);

#include <sys/utsname.h>
int uname(struct utsname *name);

p196 系统日志

æ ¹æ®ä¸åŒçš„目的,linux 下会有ä¸åŒçš„目录ä¿å­˜ç³»ç»Ÿæ—¥å¿—ä¿¡æ¯ã€‚常è§çš„的比如 /usr/adm , /var/log 下。/var/log/message åŒ…å«æ‰€æœ‰çš„系统消æ¯ï¼Œ /var/log/mail 为邮件系统的日志,/var/log/debug 为调试性信æ¯ï¼Œå¯ä»¥åœ¨ /etc/syslog.conf 或者 /etc/syslog-ng/syslog-ng.conf 看到相关目录和文件的é…置。syslog 函数用æ¥è®°å½•系统日志:

#include <syslog.h>
void syslog(int priority, const char *message, arguments...);

日志级别定义: LOG_EMERG, LOG_ALERT, LOG_CRIT, LOG_ERR, LOG_WARNING, LOG_NOTICE, LOG_INFO, LOG_DEBUG 。很多系统默认设置会把 LOG_EMERG 级的信æ¯å¹¿æ’­ç»™æ‰€æœ‰ç”¨æˆ·ï¼ŒLOG_ALERT 则是 mail 给系统管ç†å‘˜ï¼ŒLOG_DEBUG å¯èƒ½è¢«å¿½ç•¥ã€‚ 使用 syslog 的时候,å¯ä»¥å¦‚下通过 %m æ¥æ’入当å‰é”™è¯¯çš„ä¿¡æ¯(errno 对应的错误信æ¯): syslog(LOG_ERR|LOG_USER, “oops - %m\n”) 。

å¯ä»¥é€šè¿‡ setlogmask 定义需è¦è®°å½•的日志级别。

p201 资æºé™åˆ¶

出于硬件é™åˆ¶(比如内存)或者系统策略等的需è¦ï¼Œlinux 会丢一些资æºçš„使用åšé™åˆ¶ï¼Œæ¯”如å•è¿›ç¨‹åŒæ—¶æ‰“开的文件数。limits.h 中定义了一些常é‡(列了部分):

- NAME_MAX æ–‡ä»¶åæœ€å¤§å­—符数
- CHAR_BIT 字符的字节数
- CHAR_MAX 字符最大值
- INT_MAX int 型最大值

对系统资æºçš„é™åˆ¶å®šä¹‰åœ¨ sys/resource.h ä¸­ã€‚ä¸‹é¢æ˜¯èŽ·å¾—æˆ–è€…è®¾ç½®ç³»ç»Ÿèµ„æºé™åˆ¶çš„常用函数:

#include <sys/resource.h>
int getpriority(int which, id_t who);
int setpriority(int which, id_t who, int priority);
int getrlimit(int resource, struct rlimit *r_limit);
int setrlimit(int resource, const struct rlimit *r_limit);
int getrusage(int who, struct rusage *r_usage);

上é¢ç»“构中的 rusage 是表示 CPU 时间的,至少包括两个æˆå‘˜ï¼š struct timeval ru_utime 用户时间; struct timeval ru_stime 系统时间。 timeval 是 sys/time.h 中定义的包括表示秒和微秒两个æˆå‘˜çš„结构。简å•的说,系统时间就是进程使用系统调用所耗费的时间,用户时间则是进程进行系统调用之外的è¿ç®—耗费的时间。getruage 函数还å¯ä»¥ç”±å‚数指定获å–包括当å‰è¿›ç¨‹çš„å­è¿›ç¨‹çš„ä¿¡æ¯ã€‚

系统默认的进程优先级是 0 ,å¯ç”¨å€¼èŒƒå›´ä¸º -20 到 +20 。所以 getpriority 函数获得进程优先级时,返回 -1 å¯èƒ½æ˜¯å‡½æ•°æ‰§è¡Œå‡ºé”™ä¹Ÿå¯èƒ½æ˜¯ä¼˜å…ˆçº§ä¸º -1 ï¼Œè¿™æ—¶å€™å°±éœ€è¦æ£€æŸ¥ç³»ç»Ÿçš„ errno ä¸­æ˜¯å¦æœ‰å€¼äº†ã€‚

最大打开文件数等资æºé™åˆ¶å¯ä»¥ç”± getrlimit å’Œ setrlimit 获得和设置。 rlimit 结构æè¿°ä¸€ä¸ªé™åˆ¶ï¼Œä¸¤ä¸ªæˆå‘˜åˆ†åˆ«ä»£è¡¨è½¯é™åˆ¶(当å‰è¿›ç¨‹çš„é™åˆ¶)以åŠç¡¬é™åˆ¶(系统的é™åˆ¶)。定义在 sys/resource.h 的常è§é™åˆ¶:

- RLIMIT_CORE 字节表示的 cordump 文件最大值
- RLIMIT_CPU 秒为å•元的 CPU 最大使用时间
- RLIMIT_DATA ç¨‹åºæ•°æ®æ®µä½¿ç”¨çš„字节数é™åˆ¶
- RLIMIT_FSIZE 字节为å•ä½çš„æ–‡ä»¶å¤§å°é™åˆ¶
- RLIMIT_NOFILE åŒæ—¶æ‰“开最大文件数
- RLIMIT_STACK ç¨‹åºæ ˆå¤§å°(字节)
- RLIMIT_AS 地å€ç©ºé—´(栈和数æ®)é™åˆ¶

接下æ¥çš„俩章: 终端 å’Œ 基于文本和光标的å±å¹•å¤„ç†æ²¡æœ‰ä»€ä¹ˆå®žé™…价值,ä¸ç»†çœ‹ã€‚

回å¤

Security Image (验è¯ç å¿…须填写)