目录
库的定义
通俗来讲就是将用户写好的程序打包成一个整体,当其他模块或用户使用时,只需要有这个库文件就可以了,不需要源代码文件。也可以理解为一组预先编译好的方法的集合。本质上来说,库是一种可执行代码的二进制形式,可以被操作系统载入内存执行。
库:
头文件 #include“” #include <> 其他头文件
结构体 宏定义 函数声明 共用体 枚举 条件编译 重定义
例如:源文件 main.c
库的分类
静态库的制作
1. 将源文件编译生成目标文件
gcc -c xxx.c -o xxx.o
2. 创建静态库,用ar命令,将多个 .o文件准化成 .a文件
ar crs libxxx.a xxx.o
3. 测试静态库的使用
gcc main.c -L库的路径 -l库名
4. 执行 ./a.out
动态库的制作
1. 编译生成目标文件
gcc -fPIC -c xxx.c -o xxx.o
2.创建共享库
gcc shared -o libxxx.so xxx.o
3. 测试动态库的使用
gcc main.c -L库的路径 -l库名
4. 执行 ./a.out
以上步骤可以编译通过,但是运行时会报错
错误展示:
原因:
动态库是在实际运行时载入,当加载动态库时,系统会默认从 /lib或 /usr/lib 路径下查找库文件
解决方法:
1. 把库文件拷贝到 /usr/lib 和 /lib 目录下(此方法适用于编译时不需要指定库的路径)
2. 在 LD_LIBRARY_PATH 环境变量中加上库所在的路径。
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:.
(终端关闭,环境变量就不在了)
3. 添加 /etc/ld.so.conf.d/*.conf文件,把库所在的路径加到文件末尾,并执行ldconfig刷新
sudo vi /etc/ld.so.conf.d/*.conf
添加动态库存在的路径,例如:
/home/hq/teach/23043/IO/day3/share
添加成功后用 wq!保存退出,之后刷新:sudo ldconfig
动态库和静态库的区别
本质区别:动态库和静态库的本质区别是代码被载入的时刻不同。
静态库
静态库在程序编译时会被连接到目标代码中。
优点:程序运行时将不再需要该静态库;运行时无需加载库,运行速度更快
缺点:静态库重点代码复制到了程序中,因此体积较大;静态库升级后,程序需要重新编译链接
动态库
动态库在程序运行时才被载入到代码中。
优点:程序在执行时加载动态库,代码体积较小;程序升级更简单
缺点:运行时还需要动态库的存在,移植性较差
文件属性获取
获取文件属性
stat
格式:int stat(const char *path, struct stat *buf);
功能:获取文件属性
参数:
path:文件路径名
buf:保存文件属性信息的结构体
返回值:
成功:0
失败:-1
struct stat {
dev_t st_dev; /* 设备包含文件ID */
ino_t st_ino; /* inode号 */
mode_t st_mode; /* 文件类型和权限 */
nlink_t st_nlink; /* 硬链接数 */
uid_t st_uid; /* 用户ID */
gid_t st_gid; /* 组ID */
off_t st_size; /* 大小 */
dev_t st_rdev; /* 设备ID */
time_t st_atime; /* 最后访问时间 */
time_t st_mtime; /* 最后修改时间 */
time_t st_ctime; /* 最后状态改变时间 */
};
获取用户属性
getpwuid
格式:struct passwd *getpwuid(uid_t uid);
功能:通过用户 id 获取用户属性
参数:uid:用户 id
返回值:
返回保存用户相关属性结构体的地址
失败:NULL
struct passwd {
char *pw_name; /* 用户名 */
char *pw_passwd; /* 密码 */
uid_t pw_uid; /* user ID */
gid_t pw_gid; /* group ID */
char *pw_gecos; /* 真实名 */
char *pw_dir; /* 主目录 */
char *pw_shell; /* 使用的shell */
};
获取组属性
getgrgid
格式:struct group *getgrgid(gid_t gid);
功能:通过组 id 获取组属性
参数:gid:组 id
返回值:返回保存组相关属性结构体的地址 err:NULL
struct group {
char *gr_name; /* 组名 */
char *gr_passwd; /* 组密码 */
gid_t gr_gid; /* 组ID */
char **gr_mem; /*组成员账号 */
};
将时间转化为字符串
ctime
格式:char *ctime(const time_t *timep);
功能:将时间秒数转化为字符串表示
参数:timep :时间
返回值:成功返回字符串首地址
失败:NULL
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <pwd.h>
#include <time.h>
int main(int argc, char const *argv[])
{
struct stat buf;
if (stat("./1ls.c", &buf) < 0)
{
perror("stat err");
return -1;
}
printf("inod:%lu nlink:%d\n",
buf.st_ino, buf.st_nlink);
printf("mode:%#o\n", buf.st_mode);
//获取文件类型
if ((buf.st_mode & S_IFMT) == S_IFREG)
printf("-\n");
if ((buf.st_mode & S_IFMT) == S_IFDIR)
printf("d\n");
if (S_ISREG(buf.st_mode))
putchar('-');
//获取文件权限
if (buf.st_mode & S_IRUSR)
printf("r");
else
printf("-");
//获取用户名
printf(" %s ", getpwuid(buf.st_uid)->pw_name);
//获取时间
printf("%.12s ", ctime(&buf.st_mtime)+4);
putchar(10);
return 0;
}
练习1:
用stat完成 ls -l 文件名 功能
文件权限:
首先和4位与操作看是否有r权限,再和2位与看是否有w权限,再和1位与看是否有x权限
通过位移操作和每一个权限相与看是否有权限
0400:十进制数,每一组权限都有rwx三种,最高位权限有的话,其二进制数为100,位与后再右移一位。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <pwd.h>
#include <grp.h>
#include <time.h>
int main(int argc, const char *argv[])
{
struct stat buf;
if (stat(argv[1], &buf) < 0)
{
perror("error \n");
return -1;
}
//判断文件类型
if (S_ISREG(buf.st_mode))
printf("-");
else if (S_ISDIR(buf.st_mode))
printf("d");
else if (S_ISSOCK(buf.st_mode))
printf("s");
else if (S_ISBLK(buf.st_mode))
printf("b");
else if (S_ISFIFO(buf.st_mode))
printf("p");
else if (S_ISLNK(buf.st_mode))
printf("l");
else if (S_ISCHR(buf.st_mode))
printf("c");
/*
//user
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("-");
//group
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("-");
//other
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("-");
*/
//获取文件权限
char arr[3] = "rwx";
for (int i = 0; i < 9; i++)
(buf.st_mode & (0400 >> i)) ? printf("%c", arr[i % 3]) : printf("-");
//硬链接个数
printf(" %d", buf.st_nlink);
//uid:hq
printf(" %s", getpwuid(buf.st_uid)->pw_name);
//gid:hq
printf(" %s", getgrgid(buf.st_gid)->gr_name);
//文件大小
printf(" %ld", buf.st_size);
//最后更新时间
printf(" %.12s", 4 + ctime(&buf.st_mtime)); //4+:跳过前四位,.12位宽12右对齐
//文件名
printf(" %s", argv[1]);
putchar('\n');
return 0;
}