Unix上機課已經進行5次了,信息量越來越大,需要記的東西也越來越多。於是決定把一些重要的東西記在這裏跟大家分享。
在法國學計算機一個很大的感觸就是實踐所佔的比重相當大,大課的信息量極大,很難記住什麼東西,但是與之輔助的小課實在是十分奏效。小課以20人的小班爲單位,這就是人少的好處,能保證每個人都掌握相關的知識。這邊的課確實比在國內深多了,能看出老師確實有很高的水平,講的很深很細緻。
Unix系統課已經上了很多節,這裏只記錄上機課的一些個人認爲重要的知識點。前兩節小課主題是Bash 基本命令,再此不記錄了,這裏主要涉及通過unix下的c語言編程瞭解系統原理。
第一課
1, 寫一個c程序,打印從終端傳入的參數。注意當參數爲*結果。
主函數生命爲 void main(int argc, char ** argv)即可。argc爲參數個數, argv爲參數列表,注意argv[0]爲命令本身,之後才爲真正參數。
2,寫一個程序,實現與"ls -il"相同的功能,即輸出當前目錄所有文件的有用信息,如訪問模式,鏈接個數,最近修改時間等等。此函數利用了第一題的知識,即*會被翻譯成當前目錄下的所有文件。下面的程序在終端調用時參數爲*。
主要使用stat()函數。見man lstat, 需要詳細閱讀。stat能把相應文件的所有信息返回至一個結構體裏。獲得所有者用戶名時用到getpwuid,組用戶名時用到getgrgid, 相關函數還有ctime. 代碼:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <pwd.h>
#include <grp.h>
#include <time.h>
int main(int argc, char **argv)
{
int i;
struct stat fileStat
;
struct passwd *pwd;
struct group *grp;
char date[20];
// pour tous les noms de fichiers passés en paramètres
for(i = 1; i < argc; i++)
{
// collecte des infos
if(lstat(argv[i], &fileStat))
{
perror("stat");
exit(errno);
}
// numéro d'I-noeud :I-noeud個數
printf("%d ", (int)fileStat.st_ino);
// mise en forme des permissions 各種權限
switch(fileStat.st_mode & S_IFMT)
{
case S_IFSOCK : printf("s"); break;
case S_IFLNK : printf("l"); break;
case S_IFREG : printf("-"); break;
case S_IFBLK : printf("b"); break;
case S_IFDIR : printf("d"); break;
case S_IFCHR : printf("c"); break;
case S_IFIFO : printf("p"); break;
default : printf("?");
}
if((fileStat.st_mode & S_IRUSR) == S_IRUSR) printf("r"); else printf("-");
if((fileStat.st_mode & S_IWUSR) == S_IWUSR) printf("w"); else printf("-");
if((fileStat.st_mode & S_IXUSR) == S_IXUSR)
if((fileStat.st_mode & S_ISUID) == S_ISUID) printf("s"); else printf("x");
else
if((fileStat.st_mode & S_ISUID) == S_ISUID) printf("S"); else printf("-");
if((fileStat.st_mode & S_IRGRP) == S_IRGRP) printf("r"); else printf("-");
if((fileStat.st_mode & S_IWGRP) == S_IWGRP) printf("w"); else printf("-");
if((fileStat.st_mode & S_IXGRP) == S_IXGRP)
if((fileStat.st_mode & S_ISGID) == S_ISGID) printf("s"); else printf("x");
else
if((fileStat.st_mode & S_ISGID) == S_ISGID) printf("S"); else printf("-");
if((fileStat.st_mode & S_IROTH) == S_IROTH) printf("r"); else printf("-");
if((fileStat.st_mode & S_IWOTH) == S_IWOTH) printf("w"); else printf("-");
if((fileStat.st_mode & S_IXOTH) == S_IXOTH)
if((fileStat.st_mode & S_ISVTX) == S_ISVTX) printf("t"); else printf("x");
else
if((fileStat.st_mode & S_ISVTX) == S_ISVTX) printf("T"); else printf("-");
// nombre de liens dur 硬鏈接個數
printf(" %d ", (int)fileStat.st_nlink);
// nom du propriétaire 所有者用戶名
if ((pwd = getpwuid(fileStat.st_uid)) != NULL)
printf("%s ", pwd->pw_name);
else
printf("%d ", fileStat.st_uid);
// nom du groupe 組用戶名
if ((grp = getgrgid(fileStat.st_gid)) != NULL)
printf("%s ", grp->gr_name);
else
printf("%d ", fileStat.st_gid);
// taille du fichier en octets 文件大小
printf("%d ", (int)fileStat.st_size);
// date de dernière modification 修改時間
strftime(date, 20, "%Y-%m-%d %H:%M", gmtime(&fileStat.st_mtime));
printf("%s ", date);
// nom du fichier et saut de ligne 文件名
printf("%s\n", argv[i]);
}
return 0;
}
3,如果不使用*,要如何遍歷當前目錄下的文件?
涉及到man opendir。
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <pwd.h>
#include <grp.h>
#include <time.h>
#include <dirent.h>
int main(int argc, char **argv)
{
DIR *directory;
struct dirent *file;
struct stat fileStat;
struct passwd *pwd;
struct group *grp;
char date[20];
// le nom du répertoir à lire doit être passé en premier paramètre
if(argc < 2) exit(-1);
// ouverture du répertoire
if((directory = opendir(argv[1])) == NULL) { perror("opendir"); exit(errno); }
// pour tous les fichiers du répertoire
while((file = readdir(directory)) != NULL)
{
// collecte des infos
if(lstat(file->d_name, &fileStat)) { perror("stat"); exit(errno); }
// numéro d'I-noeud
printf("%d ", (int)fileStat.st_ino);
// mise en forme des permissions
switch(fileStat.st_mode & S_IFMT)
{
case S_IFSOCK : printf("s"); break;
case S_IFLNK : printf("l"); break;
case S_IFREG : printf("-"); break;
case S_IFBLK : printf("b"); break;
case S_IFDIR : printf("d"); break;
case S_IFCHR : printf("c"); break;
case S_IFIFO : printf("p"); break;
default : printf("?");
}
if((fileStat.st_mode & S_IRUSR) == S_IRUSR) printf("r"); else printf("-");
if((fileStat.st_mode & S_IWUSR) == S_IWUSR) printf("w"); else printf("-");
if((fileStat.st_mode & S_IXUSR) == S_IXUSR)
if((fileStat.st_mode & S_ISUID) == S_ISUID) printf("s"); else printf("x");
else
if((fileStat.st_mode & S_ISUID) == S_ISUID) printf("S"); else printf("-");
if((fileStat.st_mode & S_IRGRP) == S_IRGRP) printf("r"); else printf("-");
if((fileStat.st_mode & S_IWGRP) == S_IWGRP) printf("w"); else printf("-");
if((fileStat.st_mode & S_IXGRP) == S_IXGRP)
if((fileStat.st_mode & S_ISGID) == S_ISGID) printf("s"); else printf("x");
else
if((fileStat.st_mode & S_ISGID) == S_ISGID) printf("S"); else printf("-");
if((fileStat.st_mode & S_IROTH) == S_IROTH) printf("r"); else printf("-");
if((fileStat.st_mode & S_IWOTH) == S_IWOTH) printf("w"); else printf("-");
if((fileStat.st_mode & S_IXOTH) == S_IXOTH)
if((fileStat.st_mode & S_ISVTX) == S_ISVTX) printf("t"); else printf("x");
else
if((fileStat.st_mode & S_ISVTX) == S_ISVTX) printf("T"); else printf("-");
// nombre de liens dur
printf(" %d ", (int)fileStat.st_nlink);
// nom du propriétaire
if ((pwd = getpwuid(fileStat.st_uid)) != NULL)
printf("%s ", pwd->pw_name);
else
printf("%d ", fileStat.st_uid);
// nom du groupe
if ((grp = getgrgid(fileStat.st_gid)) != NULL)
printf("%s ", grp->gr_name);
else
printf("%d ", fileStat.st_gid);
// taille du fichier en octets
printf("%d ", (int)fileStat.st_size);
// date de dernière modification
strftime(date, 20, "%Y-%m-%d %H:%M", gmtime(&fileStat.st_mtime));
printf("%s ", date);
// nom du fichier et saut de ligne
printf("%s\n", file->d_name);
}
// si une erreur s'est produite sur "readdir"
if(errno != 0) { perror("stat"); exit(errno); }
return 0;
}
ok先到這,有時間繼續整理