Linux 环境2(Beginning Linux Programming 笔记9)
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 <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 :
time_t mktime(struct tm *timeptr);
å¦å¤– asctime 函数å¯ä»¥æŠŠ tm ç»“æž„è½¬æ¢æˆ”Sun Jun 9 12:34:56 2007\n\0″è¿™æ ·çš„å—符串。 ctime 则相当于下é¢çš„第四行代ç :
char *asctime(const struct tm *timeptr);
char *ctime(const time_t *timeval);
asctime(localtime(timeval));
p186 strftime ç”¨æ¥æ ¼å¼åŒ–输出自定义的å¯è¯»çš„æ—¶é—´æ ¼å¼ã€‚
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 功能类似:
char *strptime(const char *buf, const char *format, struct tm *timeptr);
使用例å:
#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 = ×truct;
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 时,生æˆçš„æ–‡ä»¶å会赋予给该å˜é‡ï¼š
char *tmpnam(char *s);
å¦‚æžœç”Ÿæˆæ–‡ä»¶å以åŽé©¬ä¸Šå°±éœ€è¦åˆ›å»ºæ–‡ä»¶ï¼Œå¯ä»¥ç›´æŽ¥ä½¿ç”¨ tmpfile å‡½æ•°ï¼Œè¿™æ ·èƒ½é˜²æ¢åœ¨ç”Ÿæˆæ–‡ä»¶å到创建文件的过程ä¸ï¼Œå¦å¤–ä¸€ä¸ªè¿›ç¨‹åˆ›å»ºäº†åŒæ ·çš„æ–‡ä»¶ã€‚
FILE *tmpfile(void);
该函数返回指å‘ä¸´æ—¶æ–‡ä»¶çš„æ–‡ä»¶æµæŒ‡é’ˆï¼Œå¹¶ä¸”ä»¥è¯»å†™æ–¹å¼æ‰“开文件,当所有指å‘è¯¥æ–‡ä»¶çš„å¼•ç”¨è¢«å…³é—æ—¶ï¼Œä¸´æ—¶æ–‡ä»¶ä¼šè¢«è‡ªåŠ¨åˆ é™¤ã€‚æ³¨æ„å› ä¸ºæœ‰ä¸Šé¢è¯´åˆ°çš„风险,所以一般创建临时文件都用 tmpfile æ¥ï¼Œå®žé™…上 GNU C 编译器会对 tmpname çš„ä½¿ç”¨äº§ç”Ÿä¸€æ¡ warning 。å¦å¤–,æŸäº› UNIX ç‰ˆæœ¬ä¸æä¾›å¦å¤–ä¸€ç§æ–¹å¼:
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 <unistd.h>
uid_t getuid(void);
char *getlogin(void);
系统文件 /etc/passwd ä¸ä¿å˜ç€ç³»ç»Ÿç”¨æˆ·çš„ä¿¡æ¯ï¼Œæ¯è¡Œä¸ºä¸€ä¸ªç”¨æˆ·çš„ä¿¡æ¯: 用户å:åŠ å¯†å¯†ç :UID:GID/å…¨å:HOME目录:默认shell ,比如:
现在的大多数系统ä¸å·²ç»ä¸å†æŠŠå¯†ç åŠ å¯†ä¸²ä¿å˜åœ¨è¿™é‡Œï¼Œè€Œæ˜¯ä½¿ç”¨”å½±å密ç (shadow password)”文件,一般在 /etc/shadow ,通过é™åˆ¶å¯¹å®ƒçš„æ“ä½œï¼Œæ¥åŠ å¼ºç³»ç»Ÿçš„å®‰å…¨æ€§ã€‚
我们å¯ä»¥é€šè¿‡ä¸‹é¢çš„函数获得用户的信æ¯:
#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 <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 å¯ä»¥èŽ·å¾—æ›´å¤šçš„ä¸»æœºä¿¡æ¯ï¼ŒåŒ…括æ“作系统以åŠéƒ¨åˆ†ç¡¬ä»¶ä¿¡æ¯ã€‚
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 函数用æ¥è®°å½•系统日志:
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 ä¸ã€‚䏋颿˜¯èŽ·å¾—æˆ–è€…è®¾ç½®ç³»ç»Ÿèµ„æºé™åˆ¶çš„常用函数:
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 地å€ç©ºé—´(æ ˆå’Œæ•°æ®)é™åˆ¶
接下æ¥çš„ä¿©ç« ï¼š 终端 å’Œ åŸºäºŽæ–‡æœ¬å’Œå…‰æ ‡çš„å±å¹•å¤„ç†æ²¡æœ‰ä»€ä¹ˆå®žé™…价值,ä¸ç»†çœ‹ã€‚

回å¤