1. 计算机大小端,代码参见 big_little.c
#include <stdio.h>
int main(void) {
short var_a = 0x0001;
char *var_c = (char *)&var_a;
if(*var_c) {
printf("little ...\n");
}
else
printf("big ...\n");
return 0;
}
2. 写一个函数实现strcpy字符串拷贝功能,代码参见 mystrcpy.c
char *t_strcpy(char *dest, const char *src);
返回值为什么是char *,而不是 void? "方便函数嵌套调用"用法2和3
char buf[12], buff[12];
t_strcpy(buf, "tarena"); //可能用法1
strlen(t_strcpy(buf, "tarena")); //可能用法2
t_strcpy(buff, t_strcpy(buf, "tarena")); //可能用法3,嵌套2次拷贝
#include <stdio.h>
#include <string.h> //strlen
//dest:值-结果参数
char *t_strcpy1(char *dest, const char *src) {
char *p_tmp = dest;
while(*p_tmp++ = *src++); //linux内核
return dest;
}
char *t_strcpy2(char *dest, const char *src) {
char *p_tmp = dest;
while(*src = '\0') {
*p = *src;
p++, src++;
}
*p = *src; //或 *p = '\0';
return dest;
}
int main(void) {
char buf[12] = {0}, buff[12] = {0};
char *s = "tarena";
t_strcpy(buf, s);
printf("buf content: %s\n", buf);
int size = strlen(t_strcpy(buf, s));//需要string.h
printf("strlen(buf) = %d\n", size);
t_strcpy(buff, t_strcpy(buf, s));
printf("buff content: %s\n", buff);
return 0;
}
一、获取文件的源数据
什么是文件元数据?
"文件的元数据"就是文件的属性。
文件有文件的"内容"和文件的"属性"。
[-][rw-][rw-][r--] 1 tarena tarena 489 12月 6 09:49 //mystrcpy.c
[1][234][567][890] (除了文件名以外,都是文件的属性,即文件的元数据)
[1]代表文件的类型:
"-" 普通文件 S_IFREG
"d" 文件夹文件 S_IFDIR
"c" 字符设备文件 S_IFCHR
"b" 块设备文件 S_IFBLK
"s" 通讯文件 S_IFSOCK
"l" 软链接文件 S_IFLNK
"p" 管道文件 S_IFIFO "?"
tarena(1) 属主,每个用户都有自己的身份证号,叫"uid"
属主的信息存放在" /etc/passwd/ "文件中
cat /etc/passwd
root:x:0:0:root:/root:/bin/bash //第一行
root 用户名
x 有密码标记,删除就无密码了
0 uid (可记)
0 gid
root 用户的简单备注说明
/root 用户工作的主目录,"~"是其简写
/bin/bash 用户启动的第一个程序bash
tarena(2) 属组,每个属组也有自己的身份证号,叫组id="gid"
属组的信息存放在" /etc/group/ "文件中
cat /etc/group
补充:
1)"stat"也可以查看文件的元数据
"格式:stat 文件名" //查看文件的元数据(属性)
2)链接文件
文件属性中的第一个 1 是硬链接数
每个文件都有且仅有一个自己的"inode"
但是一个inode可以对应多个文件的名字
"硬链接"的inode是同一个,"软链接"不是同一个(软链接也叫符号链接)。
链接的创建和使用
ln hello h //建立hello和h的硬链接,使用 stat hello 和 stat h查看
ln -s hello fileA //建立hello和fileA的软链接"fileA"->"hello"
通过系统调用获取文件的属性
"stat"(2)
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int stat(const char *path, struct stat *buf);
功能:获取文件的属性
参数:
"path" 文件路径,要获取属性的文件地址
"buf" 将文件的属性填充到buf指定的空间里
补充:
struct stat /*存放文件属性的结构体*/
struct stat {
dev_t st_dev; /* 用于设备文件描述符 */ignore
ino_t st_ino; /* inode号 */ 1
mode_t st_mode; /* 类型/权限protection */ 1
nlink_t st_nlink; /* 硬链接数 */ 1
uid_t st_uid; /* 属主user ID */ 1
gid_t st_gid; /* 属组组ID */ 1
dev_t st_rdev; /* 设备文件ID */ignore
off_t st_size; /* 总字节长度 */ 1
blksize_t st_blksize; /* blocksize for file system I/O */ignore
blkcnt_t st_blocks; /* number of 512B blocks allocated*/ignore
time_t st_atime; /* 最后一次访问时间 */ 1
time_t st_mtime; /* 最后修改时间 */ 1
time_t st_ctime; /* 状态改变时间 */ 1
};
返回值:
成功 - 返回 0
失败 - 返回 -1,errno被设置
/*举例验证,文件元数据的获取,代码参见 stat.c*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <pwd.h>
int main(int argc, char *argv[]) {
struct stat buf;
int r = stat(argv[1], &buf); //获取文件的属性
if(r == -1) { //stat函数调用失败
perror("stat");
return 1;
}
printf("stat success...\n");
printf("inode number: %lu\n", buf.st_ino);
printf("hard links: %d\n", buf.st_nlink);
printf("total size: %ld\n", buf.st_size);
printf("uid: %d\n", buf.st_uid);
struct passwd *pass = getpwuid(buf.st_uid);
if(pass == NULL) {
printf("not found...\n");
return 2;
}
printf("username: %s\n", pass->pw_name);
printf("gid: %d\n", buf.st_gid);
printf("time: %ld\n", buf.st_atime);
printf("mode: %#o\n", buf.st_mode);
if(S_ISREG(buf.st_mode)) {
printf("-");
}
else if(S_ISDIR(buf.st_mode)) {
printf("d");
}
printf("######################\n");
switch(buf.st_mode & S_IFMT) { //做与操作
case S_IFREG:
printf("-");
break;
case S_IFDIR:
printf("d");
break;
default:
break;
}
printf("\n");
if(buf.st_mode & S_IRUSR) {
printf("r");
} else
printf("-");
if(buf.st_mode & S_IWUSR) {
printf("w");
} else
printf("-");
if(buf.st_mode & S_IXUSR) {
printf("x");
} else
printf("-");
if(buf.st_mode & S_IRGRP) {
printf("r");
} else
printf("-");
if(buf.st_mode & S_IWGRP) {
printf("w");
} else
printf("-");
if(buf.st_mode & S_IXGRP) {
printf("x");
} else
printf("-");
if(buf.st_mode & S_IROTH) {
printf("r");
} else
printf("-");
if(buf.st_mode & S_IWOTH) {
printf("w");
} else
printf("-");
if(buf.st_mode & S_IXOTH) {
printf("x");
} else
printf("-");
printf("\n");
return 0;
}
补充:
通过getpwnam(3)获取uid的名字
#include <sys/types.h>
#include <pwd.h>
struct passwd *getpwuid(uid_t uid);
功能:获取uid相关信息
参数:"uid" 指定的uid
返回值:
成功 - 返回一个指向 struct passwd结构体类型的变量地址
失败 - 返回 NULL,没找到或有错误产生,如果是错误,errno被设置
struct passwd {
char *pw_name; /* username */
char *pw_passwd; /* user password */
uid_t pw_uid; /* user ID */
gid_t pw_gid; /* group ID */
char *pw_gecos; /* user information */
char *pw_dir; /* home directory */
char *pw_shell; /* shell program */
};
通过getgrnam(3)获取gid的名字
#include <sys/types.h>
#include <grp.h>
struct group *getgrgid(gid_t gid);
功能:获取gid相关信息
参数:"gid"指定的gid
返回值:
成功 - 返回一个指向 struct group结构体类型的变量地址
失败 - 返回 NULL,没找到或有错误产生,如果是错误,errno被设置
struct group {
char *gr_name; /* group name */
char *gr_passwd; /* group password */
gid_t gr_gid; /* group ID */
char **gr_mem; /* group members */
};
使用ctime(3)将时间由数字转换为字符串类型时间显示
#include <time.h>
char *ctime(const time_t *timep);
功能:转换为日期和时间
参数:"timep" 指定的st_atime
返回值:
成功 - 返回时间值的描述
失败 - 返回 -1,errno被设置
struct tm {
int tm_sec; /* seconds */
int tm_min; /* minutes */
int tm_hour; /* hours */
int tm_mday; /* day of the month */
int tm_mon; /* month */
int tm_year; /* year */
int tm_wday; /* day of the week */
int tm_yday; /* day in the year */
int tm_isdst; /* daylight saving time */
};
二、文件夹的操作
drwxrwxr-x 3 tarena tarena 4096 12月 6 15:55 1206
"r" 读取文件夹的内容
"w" 更新文件夹的内容
"x" 文件夹是否允许你被通过(cd命令的是否成功)
文件夹的内容是文件夹里的文件
程序对文件夹的操作需要使用以下函数:
"opendir"(3)
#include <sys/types.h>
#include <dirent.h>
DIR *opendir(const char *name);
功能:打开一个文件夹
参数:"name" 指定了要打开的文件夹的名字
返回值:
成功 - 一个指向文件夹流的首地址的指针
失败 - 返回 NULL,errno被设置
"readdir"(3)
#include <dirent.h>
struct dirent *readdir(DIR *dirp);
功能:读取一个文件夹
参数:"dirp" opendir(3)的返回值,要读取内容的文件夹
返回值:
成功 - 返回一个结构体指针
失败 - 返回 NULL,到达文件末尾或者错误发生,如果是错误产生,errno被设置
struct dirent {
ino_t d_ino; /* inode号 */
off_t d_off; /* 下一个偏移两 */ ignore
unsigned short d_reclen; /* 记录长度 */ ignore
unsigned char d_type; /* 不被所有文件支持 */ ignore
char d_name[256]; /* 文件名filename */
};
"closedir"(3)
#include <sys/types.h>
#include <dirent.h>
int closedir(DIR *dirp);
功能:关闭一个文件夹
参数:"dirp" opendir(3)的返回值
返回值:
成功 - 返回 0
失败 - 失败 -1,errno被设置
/*举例验证,代码参见 dir_os.c*/
#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
int main(int argc, char *argv[]) {
DIR *p_dir = opendir(argv[1]);//打开命令行指定的文件夹
if(!p_dir) {
perror("opendir");
return 1;
}
printf("opendir success...\n");
struct dirent *p_dire;
//显示文件夹内所有文件inode和文件名
while((p_dire = readdir(p_dir))) {
/*if(!p_dire) {
perror("readdir");
return 2;
}*/
printf("inode: %lu ", p_dire->d_ino);
printf("filename: %s\n", p_dire->d_name);
}
closedir(p_dir);//关闭文件夹
return 0;
}
"rewinddir"(3)
#include <sys/types.h>
#include <dirent.h>
void rewinddir(DIR *dirp);
功能:重置文件夹流到文件夹的开始位置
参数:"dirp" opendir(3)的返回值
返回值:无返回值。
"telldir"(3)
#include <dirent.h>
long telldir(DIR *dirp);
功能:当前文件夹流的位置
参数:"dirp" opendir(3)的返回值
返回值:
成功 - 返回当前文件夹流的位置
失败 - 返回 -1,errno被设置
/* 举例验证,代码参见 loca_dir.c */
#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
int main(int argc, char *argv[]) {
DIR *p_dir = opendir(argv[1]);//打开命令行指定的文件夹
if(!p_dir) {
perror("opendir");
return 1;
}
printf("opendir success...\n");
long loc = telldir(p_dir);
printf("p_dir location: %ld\n", loc);//打印文件夹里内容当前位置
loc += 1; //当前位置向后移动两个文件
printf("p_dir location: %ld\n", loc);
struct dirent *p_dire = readdir(p_dir);
printf("filename: %s\n", p_dire->d_name);
rewinddir(p_dir);
loc = telldir(p_dir);
printf("p_dir location: %ld\n", loc);
printf("filename: %s\n", p_dire->d_name);//问题:移动后文件没变?
closedir(p_dir);//关闭文件夹
return 0;
}
#include <stdio.h>
int main(void) {
short var_a = 0x0001;
char *var_c = (char *)&var_a;
if(*var_c) {
printf("little ...\n");
}
else
printf("big ...\n");
return 0;
}
2. 写一个函数实现strcpy字符串拷贝功能,代码参见 mystrcpy.c
char *t_strcpy(char *dest, const char *src);
返回值为什么是char *,而不是 void? "方便函数嵌套调用"用法2和3
char buf[12], buff[12];
t_strcpy(buf, "tarena"); //可能用法1
strlen(t_strcpy(buf, "tarena")); //可能用法2
t_strcpy(buff, t_strcpy(buf, "tarena")); //可能用法3,嵌套2次拷贝
#include <stdio.h>
#include <string.h> //strlen
//dest:值-结果参数
char *t_strcpy1(char *dest, const char *src) {
char *p_tmp = dest;
while(*p_tmp++ = *src++); //linux内核
return dest;
}
char *t_strcpy2(char *dest, const char *src) {
char *p_tmp = dest;
while(*src = '\0') {
*p = *src;
p++, src++;
}
*p = *src; //或 *p = '\0';
return dest;
}
int main(void) {
char buf[12] = {0}, buff[12] = {0};
char *s = "tarena";
t_strcpy(buf, s);
printf("buf content: %s\n", buf);
int size = strlen(t_strcpy(buf, s));//需要string.h
printf("strlen(buf) = %d\n", size);
t_strcpy(buff, t_strcpy(buf, s));
printf("buff content: %s\n", buff);
return 0;
}
一、获取文件的源数据
什么是文件元数据?
"文件的元数据"就是文件的属性。
文件有文件的"内容"和文件的"属性"。
[-][rw-][rw-][r--] 1 tarena tarena 489 12月 6 09:49 //mystrcpy.c
[1][234][567][890] (除了文件名以外,都是文件的属性,即文件的元数据)
[1]代表文件的类型:
"-" 普通文件 S_IFREG
"d" 文件夹文件 S_IFDIR
"c" 字符设备文件 S_IFCHR
"b" 块设备文件 S_IFBLK
"s" 通讯文件 S_IFSOCK
"l" 软链接文件 S_IFLNK
"p" 管道文件 S_IFIFO "?"
tarena(1) 属主,每个用户都有自己的身份证号,叫"uid"
属主的信息存放在" /etc/passwd/ "文件中
cat /etc/passwd
root:x:0:0:root:/root:/bin/bash //第一行
root 用户名
x 有密码标记,删除就无密码了
0 uid (可记)
0 gid
root 用户的简单备注说明
/root 用户工作的主目录,"~"是其简写
/bin/bash 用户启动的第一个程序bash
tarena(2) 属组,每个属组也有自己的身份证号,叫组id="gid"
属组的信息存放在" /etc/group/ "文件中
cat /etc/group
补充:
1)"stat"也可以查看文件的元数据
"格式:stat 文件名" //查看文件的元数据(属性)
2)链接文件
文件属性中的第一个 1 是硬链接数
每个文件都有且仅有一个自己的"inode"
但是一个inode可以对应多个文件的名字
"硬链接"的inode是同一个,"软链接"不是同一个(软链接也叫符号链接)。
链接的创建和使用
ln hello h //建立hello和h的硬链接,使用 stat hello 和 stat h查看
ln -s hello fileA //建立hello和fileA的软链接"fileA"->"hello"
通过系统调用获取文件的属性
"stat"(2)
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int stat(const char *path, struct stat *buf);
功能:获取文件的属性
参数:
"path" 文件路径,要获取属性的文件地址
"buf" 将文件的属性填充到buf指定的空间里
补充:
struct stat /*存放文件属性的结构体*/
struct stat {
dev_t st_dev; /* 用于设备文件描述符 */ignore
ino_t st_ino; /* inode号 */ 1
mode_t st_mode; /* 类型/权限protection */ 1
nlink_t st_nlink; /* 硬链接数 */ 1
uid_t st_uid; /* 属主user ID */ 1
gid_t st_gid; /* 属组组ID */ 1
dev_t st_rdev; /* 设备文件ID */ignore
off_t st_size; /* 总字节长度 */ 1
blksize_t st_blksize; /* blocksize for file system I/O */ignore
blkcnt_t st_blocks; /* number of 512B blocks allocated*/ignore
time_t st_atime; /* 最后一次访问时间 */ 1
time_t st_mtime; /* 最后修改时间 */ 1
time_t st_ctime; /* 状态改变时间 */ 1
};
返回值:
成功 - 返回 0
失败 - 返回 -1,errno被设置
/*举例验证,文件元数据的获取,代码参见 stat.c*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <pwd.h>
int main(int argc, char *argv[]) {
struct stat buf;
int r = stat(argv[1], &buf); //获取文件的属性
if(r == -1) { //stat函数调用失败
perror("stat");
return 1;
}
printf("stat success...\n");
printf("inode number: %lu\n", buf.st_ino);
printf("hard links: %d\n", buf.st_nlink);
printf("total size: %ld\n", buf.st_size);
printf("uid: %d\n", buf.st_uid);
struct passwd *pass = getpwuid(buf.st_uid);
if(pass == NULL) {
printf("not found...\n");
return 2;
}
printf("username: %s\n", pass->pw_name);
printf("gid: %d\n", buf.st_gid);
printf("time: %ld\n", buf.st_atime);
printf("mode: %#o\n", buf.st_mode);
if(S_ISREG(buf.st_mode)) {
printf("-");
}
else if(S_ISDIR(buf.st_mode)) {
printf("d");
}
printf("######################\n");
switch(buf.st_mode & S_IFMT) { //做与操作
case S_IFREG:
printf("-");
break;
case S_IFDIR:
printf("d");
break;
default:
break;
}
printf("\n");
if(buf.st_mode & S_IRUSR) {
printf("r");
} else
printf("-");
if(buf.st_mode & S_IWUSR) {
printf("w");
} else
printf("-");
if(buf.st_mode & S_IXUSR) {
printf("x");
} else
printf("-");
if(buf.st_mode & S_IRGRP) {
printf("r");
} else
printf("-");
if(buf.st_mode & S_IWGRP) {
printf("w");
} else
printf("-");
if(buf.st_mode & S_IXGRP) {
printf("x");
} else
printf("-");
if(buf.st_mode & S_IROTH) {
printf("r");
} else
printf("-");
if(buf.st_mode & S_IWOTH) {
printf("w");
} else
printf("-");
if(buf.st_mode & S_IXOTH) {
printf("x");
} else
printf("-");
printf("\n");
return 0;
}
补充:
通过getpwnam(3)获取uid的名字
#include <sys/types.h>
#include <pwd.h>
struct passwd *getpwuid(uid_t uid);
功能:获取uid相关信息
参数:"uid" 指定的uid
返回值:
成功 - 返回一个指向 struct passwd结构体类型的变量地址
失败 - 返回 NULL,没找到或有错误产生,如果是错误,errno被设置
struct passwd {
char *pw_name; /* username */
char *pw_passwd; /* user password */
uid_t pw_uid; /* user ID */
gid_t pw_gid; /* group ID */
char *pw_gecos; /* user information */
char *pw_dir; /* home directory */
char *pw_shell; /* shell program */
};
通过getgrnam(3)获取gid的名字
#include <sys/types.h>
#include <grp.h>
struct group *getgrgid(gid_t gid);
功能:获取gid相关信息
参数:"gid"指定的gid
返回值:
成功 - 返回一个指向 struct group结构体类型的变量地址
失败 - 返回 NULL,没找到或有错误产生,如果是错误,errno被设置
struct group {
char *gr_name; /* group name */
char *gr_passwd; /* group password */
gid_t gr_gid; /* group ID */
char **gr_mem; /* group members */
};
使用ctime(3)将时间由数字转换为字符串类型时间显示
#include <time.h>
char *ctime(const time_t *timep);
功能:转换为日期和时间
参数:"timep" 指定的st_atime
返回值:
成功 - 返回时间值的描述
失败 - 返回 -1,errno被设置
struct tm {
int tm_sec; /* seconds */
int tm_min; /* minutes */
int tm_hour; /* hours */
int tm_mday; /* day of the month */
int tm_mon; /* month */
int tm_year; /* year */
int tm_wday; /* day of the week */
int tm_yday; /* day in the year */
int tm_isdst; /* daylight saving time */
};
二、文件夹的操作
drwxrwxr-x 3 tarena tarena 4096 12月 6 15:55 1206
"r" 读取文件夹的内容
"w" 更新文件夹的内容
"x" 文件夹是否允许你被通过(cd命令的是否成功)
文件夹的内容是文件夹里的文件
程序对文件夹的操作需要使用以下函数:
"opendir"(3)
#include <sys/types.h>
#include <dirent.h>
DIR *opendir(const char *name);
功能:打开一个文件夹
参数:"name" 指定了要打开的文件夹的名字
返回值:
成功 - 一个指向文件夹流的首地址的指针
失败 - 返回 NULL,errno被设置
"readdir"(3)
#include <dirent.h>
struct dirent *readdir(DIR *dirp);
功能:读取一个文件夹
参数:"dirp" opendir(3)的返回值,要读取内容的文件夹
返回值:
成功 - 返回一个结构体指针
失败 - 返回 NULL,到达文件末尾或者错误发生,如果是错误产生,errno被设置
struct dirent {
ino_t d_ino; /* inode号 */
off_t d_off; /* 下一个偏移两 */ ignore
unsigned short d_reclen; /* 记录长度 */ ignore
unsigned char d_type; /* 不被所有文件支持 */ ignore
char d_name[256]; /* 文件名filename */
};
"closedir"(3)
#include <sys/types.h>
#include <dirent.h>
int closedir(DIR *dirp);
功能:关闭一个文件夹
参数:"dirp" opendir(3)的返回值
返回值:
成功 - 返回 0
失败 - 失败 -1,errno被设置
/*举例验证,代码参见 dir_os.c*/
#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
int main(int argc, char *argv[]) {
DIR *p_dir = opendir(argv[1]);//打开命令行指定的文件夹
if(!p_dir) {
perror("opendir");
return 1;
}
printf("opendir success...\n");
struct dirent *p_dire;
//显示文件夹内所有文件inode和文件名
while((p_dire = readdir(p_dir))) {
/*if(!p_dire) {
perror("readdir");
return 2;
}*/
printf("inode: %lu ", p_dire->d_ino);
printf("filename: %s\n", p_dire->d_name);
}
closedir(p_dir);//关闭文件夹
return 0;
}
"rewinddir"(3)
#include <sys/types.h>
#include <dirent.h>
void rewinddir(DIR *dirp);
功能:重置文件夹流到文件夹的开始位置
参数:"dirp" opendir(3)的返回值
返回值:无返回值。
"telldir"(3)
#include <dirent.h>
long telldir(DIR *dirp);
功能:当前文件夹流的位置
参数:"dirp" opendir(3)的返回值
返回值:
成功 - 返回当前文件夹流的位置
失败 - 返回 -1,errno被设置
/* 举例验证,代码参见 loca_dir.c */
#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
int main(int argc, char *argv[]) {
DIR *p_dir = opendir(argv[1]);//打开命令行指定的文件夹
if(!p_dir) {
perror("opendir");
return 1;
}
printf("opendir success...\n");
long loc = telldir(p_dir);
printf("p_dir location: %ld\n", loc);//打印文件夹里内容当前位置
loc += 1; //当前位置向后移动两个文件
printf("p_dir location: %ld\n", loc);
struct dirent *p_dire = readdir(p_dir);
printf("filename: %s\n", p_dire->d_name);
rewinddir(p_dir);
loc = telldir(p_dir);
printf("p_dir location: %ld\n", loc);
printf("filename: %s\n", p_dire->d_name);//问题:移动后文件没变?
closedir(p_dir);//关闭文件夹
return 0;
}