Makefile
- app:sub.c add.c mult.c div.c main.c
- gcc sub.c add.c mult.c div.c main.c -o app
复制代码- app:sub.o add.o mult.o div.o main.o
- gcc sub.o add.o mult.o div.o main.o -o app
- sub.o:sub.c
- gcc -c sub.c -o sub.o
- add.o:add.c
- gcc -c add.c -o add.o
- mult.o:mult.c
- gcc -c mult.c -o mult.o
- div.o:div.c
- gcc -c div.c -o div.o
-
- main.o:main.c
- gcc -c main.c -o main.o
复制代码
- #定义变量
- src=sub.o add.o mult.o div.o main.o
- target=app
- $(target):$(src)
- $(CC) $(src) -o $(target)
-
- sub.o:sub.c
- gcc -c sub.c -o sub.o
- add.o:add.c
- gcc -c add.c -o add.o
- mult.o:mult.c
- gcc -c mult.c -o mult.o
- div.o:div.c
- gcc -c div.c -o div.o
-
- main.o:main.c
- gcc -c main.c -o main.o
复制代码- #定义变量
- src=sub.o add.o mult.o div.o main.o
- target=app
- $(target):$(src)
- $(CC) $(src) -o $(target)
- %.o:%.c
- $(CC) -c $< -o $@
复制代码 在目标文本text里找到符合模式pattern的文本,如果匹配的话使用replacement来替换,返回被替换后的字符串- #定义变量
- src=$(wildcard ./*.c)
- #src=sub.o add.o mult.o div.o main.o
- #在src这个文本字符串里将.c后缀,修改为.o后缀
- objs=$(patsubst %.c, %.o, $(src))
- target=app
- $(target):$(objs)
- $(CC) $(objs) -o $(target)
- %.o:%.c
- $(CC) -c $< -o $@
-
复制代码
- clean
规则定义:在Makefile中添加clean规则用于删除编译生成的中间文件(.o文件),其基本语法为:
参数说明:-f参数表示强制删除,避免因文件不存在而报错
clean文件冲突问题: 当目录中存在名为clean的文件时,执行make clean会提示"clean已是最新"而不执行删除操作,
解决方法是在Makefile中添加.PHONY: clean声明clean为伪目标,伪目标不会生成实际文件,因此不会与同名文件冲突。
- src=$(wildcard ./*.c)
- objs=$(patsubst %.c, %.o, $(src))
- target=app
- $(target):$(objs)
- $(CC) $(objs) -o $(target)
- %.o:%.c
- $(CC) -c $< -o $@
- #定义clean是一个尾目标。表示clean不需要生成文件
- .PHONY:clean
- clean:
- rm $(objs) -f
复制代码 GDB
Linux系统IO函数
IO函数
open
- /*
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- //打开一个已经存在的文件
- int open(const char *pathname, int flags);
- 参数:
- - pathname:要打开文件的路径
- - flags:对文件的操作权限设置还有其他的设置
- O_RDONLY, O_WRONLY, or O_RDWR 这三个只能选一个
- 返回值:返回一个新的文件描述符,如果调用失败,返回-1
- errno: 属于Linux系统函数库,库里面的一个全局变量,记录的是最近的错误号。
- #include <stdio.h>
- void perror(const char *s);
- s参数:用户描述,比如hello,最终输出的内容是 hello:xxx(实际的错误信息)
- 作用:打印errno对应的错误描述
- //创建一个新的文件
- int open(const char *pathname, int flags, mode_t mode);
- */
复制代码- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <stdio.h>
- #include <unistd.h>
- int main() {
- int fd = open("a.txt", O_RDONLY);
- if(fd == -1) {
- perror("open");
- }
-
- //关闭
- close(fd);
- return 0;
- }
复制代码- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- int open(const char *pathname, int flags, mode_t mode);
- 参数:
- - pathname: 要创建的文件的路径
- - flags: 对文件操作的权限和其他的设置
- - 必选项: O_RDONLY, O_WRONLY, or O_RDWR 互斥的
- - 可选项: O_CREAT 文件不存在,创建新文件
- - mode: 八进制的数,表示创建出的新的文件的操作权限,比如: 0775 (0代表八进制,7代表用户权限,7代表用户所在组的权限,5代表其他组的用户权限)
- 最终的权限是: mode & ~umask
- umask的作用是抹去某些权限
- umask 与 当前用户有关
- ~umask = 0777-umask = 0777-0002 = 0775
- 最终的权限是: 0777 & 0775 = 0775
复制代码- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <stdio.h>
- #include <unistd.h>
- int main() {
- //创建一个新的文件
- int fd = open("create.txt", O_RDWR | O_CREAT, 0777);
- if(fd == -1) {
- perror("open");
- }
- //关闭
- close(fd);
- return 0;
- }
复制代码 close
- #include <unistd.h>
- int close(int fd);
复制代码 read与write
man 2 read
man 2 write
- #include <unistd.h>
- ssize_t read(int fd, void *buf, size_t count);
- 参数:
- - fd: 文件描述符, open得到的,通过文件描述符来操作某个文件
- - buf: 需要读取数据存放的地方,数组的地址(传出参数)
- - count: 指定的数组的大小
- 返回值:
- - 成功:
- >0 : 返回实际的读取到的字节数
- =0 : 文件已经读取完了
- - 失败:
- -1 : 读取失败并设置errorno
复制代码- #include <unistd.h>
- ssize_t write(int fd, const void *buf, size_t count);
- 参数:
- - fd: 文件描述符, open得到的,通过文件描述符来操作某个文件
- - buf: 要往磁盘写入的数据
- - count: 要写的的数据的实际大小
- 返回值:
- 成功:实际写入的字节数
- 失败: -1, 写入失败并设置errorno
复制代码- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <stdio.h>
- #include <unistd.h>
- int main() {
- // 1.通过open, 只读O_RDONLY打开english.txt文件
- int srcfd = open("english.txt", O_RDONLY);
- if(srcfd == -1) {
- perror("open");
- }
- // 2.创建一个新的文件(拷贝文件)
- int destfd = open("cpy.txt", O_WRONLY | O_CREAT, 0664);
- if(destfd == -1) {
- perror("open");
- }
- // 3.频繁的读写操作
- char buf[1024] = {0};
- // int len = read(srcfd, buf, sizeof(buf));
- // printf("%s", buf);
- int len = 0;
- while((len = read(srcfd, buf, sizeof(buf))) > 0) {
- write(destfd, buf, len);
- }
- // 4.关闭文件
- close(srcfd);
- close(destfd);
- return 0;
- }
复制代码 lseek
- 标准C库的函数 man 3 fseek
- #include <stdio.h>
- int fseek(FILE *stream, long offset, int whence);
- Linux系统函数 man 2 lseek
- #include <sys/types.h>
- #include <unistd.h>
- off_t lseek(int fd, off_t offset, int whence);
- 参数:
- - fd: 文件描述符,通过open得到的,通过这个fd操作某个文件
- - offset: 偏移量
- - whence:
- SEEK_SET
- 设置文件指针的偏移量
- SEEK_CUR
- 设置偏移量:当前位置 + 第二个参数offset的值
- SEEK_END
- 设置偏移量:文件大小 + 第二个参数offset的值
- 返回值:返回文件指针的位置
复制代码
- 作用
1.移动文件指针到头文件
lseek(fd, 0, SEEK_SET)
2.用来获取当前文件指针
lseek(fd, 0, SEEK_CUR)
3.获取文件长度
lseek(fd, 0, SEEK_END)
4.拓展文件的长度: eg.当前文件10b, 110b, 增加了100个字节
lseek(fd, 100, SEEK_END)
注意要写入一次数据才生效
- 实现扩展文件大小
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <unistd.h>
- #include <stdio.h>
- int main() {
- int fd = open("hello.txt", O_RDWR);
- if(fd == -1) {
- perror("open");
- }
-
- //扩展文件长度
- int ret = lseek(fd, 100, SEEK_END);
- if(ret == -1) {
- perror("lseek");
- }
- //11+100+1=112
- write(fd, " ", 1);
- //关闭文件
- close(fd);
- return 0;
- }
复制代码 stat与lstat
man 2 stat
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <unistd.h>
- int stat(const char *pathname, struct stat *statbuf);
- 作用: 获取一个文件相关的信息
- 参数:
- - pathname: 文件路径
- - statbuf: 结构体变量,传出参数,用于保存获取到的文件信息
- 返回值:
- 成功:返回0
- 失败:返回-1 设置errno
- int lstat(const char *pathname, struct stat *statbuf);
- 作用: 获取一个文件相关的信息
- 参数:
- - pathname: 文件路径
- - statbuf: 结构体变量,传出参数,用于保存获取到的文件信息
- 返回值:
- 成功:返回0
- 失败:返回-1 设置errno
复制代码- #include <sys/types.h>
- #include <sys/stat.h>
- #include <unistd.h>
- #include <stdio.h>
- int main() {
- struct stat statbuf;
- int ret = stat("a.txt", &statbuf);
- if(ret == -1) {
- perror("stat");
- }
- printf("size: %ld\n", statbuf.st_size);
- return 0;
- }
复制代码
- 软链接:
ln -s a.txt b.txt
- stat与lstat的区别
- 当文件是一个符号链接时,
- lstat返回的是该符号链接本身的信息;
- 而stat返回的是该链接指向的文件的信息。
复制代码 实现ls-l命令
- #include <stdio.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <unistd.h>
- #include <pwd.h>
- #include <grp.h>
- #include <time.h>
- #include <string.h>
- //模拟实现 ls -l命令
- //-rw-rw-r-- 1 chan chan 11 9月 6 17:51 a.txt
- int main(int argc, char *argv[]) {
- //判断输入的参数是否正确
- if(argc < 2) {
- printf("%s filename\n", argv[0]);
- return 0;
- }
- //通过用户传入的文件名,调用stat获取文件信息
- struct stat statbuf;
- int ret = stat(argv[1], &statbuf);
- if(ret == -1) {
- perror("stat");
- return 0;
- }
- //1. 获取文件类型与文件权限
- char perms[11] = {0}; //用于保存文件类型与文件权限
- switch (statbuf.st_mode & S_IFMT) {
- case S_IFLNK:
- perms[0] = 'l';
- break;
- case S_IFREG:
- perms[0] = '-';
- break;
- case S_IFBLK:
- perms[0] = 'b';
- break;
- case S_IFDIR:
- perms[0] = 'd';
- break;
- case S_IFCHR:
- perms[0] = 'c';
- break;
- case S_IFIFO:
- perms[0] = 'p';
- break;
- case S_IFSOCK:
- perms[0] = 's';
- break;
- default:
- perms[0] = '?';
- break;
- }
-
- // 判断文件的访问权限
- perms[1] = (statbuf.st_mode & S_IRUSR) ? 'r':'-';
- perms[2] = (statbuf.st_mode & S_IWUSR) ? 'w':'-';
- perms[3] = (statbuf.st_mode & S_IXUSR) ? 'x':'-';
- perms[4] = (statbuf.st_mode & S_IRGRP) ? 'r':'-';
- perms[5] = (statbuf.st_mode & S_IWGRP) ? 'w':'-';
- perms[6] = (statbuf.st_mode & S_IXGRP) ? 'x':'-';
- perms[7] = (statbuf.st_mode & S_IROTH) ? 'r':'-';
- perms[8] = (statbuf.st_mode & S_IWOTH) ? 'w':'-';
- perms[9] = (statbuf.st_mode & S_IXOTH) ? 'x':'-';
- // 2.硬连接数
- int linknum = statbuf.st_nlink;
- // 3.文件所有者: 可以通过statbuf.st_uid得到uid, 然后通过getpwuid来获取用户名; man 3 getpwuid可查看
- char * fileUser = getpwuid(statbuf.st_uid)->pw_name;
- // 4.文件所在组: 可以通过statbuf.st_gid得到gid, 然后通过getgrgid来获取用户名; man 3 getpwgid可查看
- char * fileGrp = getgrgid(statbuf.st_gid)->gr_name;
- // 5.获取大小
- long int fileSize = statbuf.st_size;
- // 6.获取修改时间 statbuf.st_mtime:从1980年到修改时间的一个秒数,使用ctime转换,以换行结尾
- char * time = ctime(&statbuf.st_mtime);
- char mtime[512] = {0};
- strncpy(mtime, time, strlen(time)-1);
- char buf[1024];
- sprintf(buf, "%s %d %s %s %ld %s %s", perms, linknum, fileUser, fileGrp, fileSize, mtime, argv[1]);
- printf("%s\n", buf);
- return 0;
- }
复制代码 文件操作函数
文件属性操作函数
access
man 2 access
- #include <unistd.h>
- int access(const char *pathname, int mode);
- 作用:判断某个文件是否有某个权限(R_OK,W_OK,X_OK),或者判断文件是否存在(F_OK)
- 参数:
- - pathname: 判断的文件路径
- - mode:
- R_OK,W_OK,X_OK,F_OK 读,写,执行,文件存在
- 返回值:成功返回0,失败返回1
复制代码- #include <unistd.h>
- #include <stdio.h>
- int main() {
- int ret = access("a.txt", F_OK);
- if(ret == -1) {
- perror("access");
- return -1;
- }
- printf("文件存在!!!\n");
- return 0;
- }
复制代码 chmod
- #include <sys/stat.h>
- int chmod(const char *pathname, mode_t mode);
- 作用:修改文件的权限
- 参数:
- - pathname: 修改的文件的路径
- - mode: 需要修改的权限值,八进制数
- 返回值:
- On success, zero is returned. On error, -1 is returned, and errno is set appropriately.
-
复制代码- #include <sys/stat.h>
- #include <stdio.h>
- int main() {
- int ret = chmod("a.txt", 0775);
- if(ret == -1) {
- perror("chmod");
- return -1;
- }
- printf("修改成功!\n");
- return 0;
- }
复制代码 chown
- 改变用户所属组
- sudo useradd 用户名 添加用户
- /vim/passwd 可查看所有用户
- /vim/group 可查看每个用户的组情况
- id 用户名 查看用户所属组信息
复制代码
- #include <unistd.h>
- int chown(const char *pathname, uid_t owner, gid_t group);
- 作用:让目标用户,uid 归属于gid下
复制代码 truncate
- #include <unistd.h>
- #include <sys/types.h>
- int truncate(const char *path, off_t length);
- 作用:缩减或者扩展文件的尺寸至指定的大小
- 参数:
- - path: 需要修改的文件的路径
- - length: 最终文件需要变成的大小
- 返回值:
- On success, zero is returned. On error, -1 is returned, and errno is set appropriately.
复制代码- #include <unistd.h>
- #include <sys/types.h>
- #include <stdio.h>
- int main() {
- int ret = truncate("b.txt", 5);
- if(ret == -1) {
- perror("truncate");
- return -1;
- }
- printf("修改文件大小成功\n");
- return 0;
- }
复制代码 目录操作函数
mkdir
创建文件夹
- #include <sys/stat.h>
- #include <sys/types.h>
- int mkdir(const char *pathname, mode_t mode);
- 作用:创建一个目录
- 参数:
- pathname: 创建的目录的路径
- mode: 权限,八进制的数
- 返回值:
- return zero on success, or -1 if an error occurred (in which case, errno is set appropriately).
复制代码- #include <sys/stat.h>
- #include <sys/types.h>
- #include <stdio.h>
- int main() {
- int ret = mkdir("a", 0777);
- if(ret == -1) {
- perror("mkdir");
- return -1;
- }
- printf("创建文件夹成功\n");
- return 0;
- }
复制代码 rmdir
删除目录
rename
修改名字
- #include <stdio.h>
- int rename(const char *oldpath, const char *newpath);
- 返回值
- On success, zero is returned. On error, -1 is returned, and errno is set appropriately.
复制代码- #include <stdio.h>
- int main() {
- int ret = rename("a","b");
- if(ret == -1) {
- perror("rename");
- return -1;
- }
- printf("修改成功\n");
- return 0;
- }
复制代码 chdir与getcwd
- #include <unistd.h>
- int chdir(const char *path);
- 作用:修改进程的工作目录
- 比如在/home/chan 启动了一个可执行的程序a.out,进程的工作目录 /home/chan
- 参数:
- path: 需要修改的工作目录
- 返回值:
- On success, zero is returned. On error, -1 is returned, and errno is set appropriately.
- #include <unistd.h>
- char *getcwd(char *buf, size_t size);
- 作用:获取当前工作目录
- 参数:
- - buf: 存储的路径,指向一个数组(传出参数)
- - size: 数组大小
- 返回值:
- 返回指向的一块内存,这个数据就是第一个参数
复制代码- #include <unistd.h>
- #include <stdio.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- int main() {
- char buf[128];
- getcwd(buf, sizeof(buf));
- printf("当前的工作目录是:%s\n", buf);
- //修改工作目录
- int ret = chdir("b");
- if(ret == -1) {
- perror("chdir");
- return -1;
- }
- printf("修改后的工作目录是:b\n");
- //创建一个新文件
- int fd = open("chdir.txt", O_WRONLY|O_CREAT, 0664);
- if(fd == -1) {
- perror("open");
- return -1;
- }
- close(fd);
- //获取当前的工作路径
- char buff[128];
- getcwd(buff, sizeof(buff));
- printf("当前的工作目录是:%s\n", buff);
- return 0;
- }
复制代码 目录遍历函数
opendir
man 3 opendir
- // 打开一个目录
- #include <sys/types.h>
- #include <dirent.h>
- DIR *opendir(const char *name);
- 参数:
- - name: 打开的目录名
- 返回:
- DIR * 类型, 一个目录流
- 失败返回NULL
复制代码 readdir
man 3 readdir
- // 读取目录的数据
- #include <dirent.h>
- struct dirent *readdir(DIR *dirp);
- - 参数: dirp是opendir返回的目录流
- - 返回:
- dirent结构体, 代表读取到的文件信息
- 读取到了末尾或者失败了返回NULL
- struct dirent {
- ino_t d_ino;
- off_t d_off;
- unsigned short d_reclen;
- unsigned char d_type;
- char d_name[256];
- };
复制代码 closedir
man 3 closedir
- // 关闭目录
- #include <sys/types.h>
- #include <dirent.h>
- int closedir(DIR *dirp);
复制代码 递归获取目录下的普通文件个数
- #include <sys/types.h>
- #include <dirent.h>
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- //读取某个目录下的所有普通文件的个数
- int FileNum(const char *path);
- int main(int argc, char *argv[]) {
- if(argc < 2) {
- printf("%s path\n", argv[0]);
- return -1;
- }
- printf("普通文件个数为%d\n", FileNum(argv[1]));
- return 0;
- }
- // 用于获取目录下所有所有普通文件的个数
- int FileNum(const char *path) {
- int cnt = 0;
- // 1.打开目录
- DIR *dir = opendir(path);
- if(dir == NULL) {
- perror(NULL);
- exit(0);
- }
- // 2.循环读取dir
- struct dirent *ptr;
- while((ptr=readdir(dir)) != NULL) {
- // 获取名称 (目的是过滤掉 ./ 和 ../)
- char *dname = ptr->d_name;
- if(strcmp(dname,".") == 0||strcmp(dname,"..") == 0) {
- continue;
- }
- // 判断是普通文件还是目录
- // 如果是目录
- if(ptr->d_type == DT_DIR) {
- // 递归读取这个目录, 需要在path后加上/dname
- char newpath[256];
- sprintf(newpath, "%s/%s", path, dname);
- cnt += FileNum(newpath);
- }
- // 如果是普通文件
- if(ptr->d_type == DT_REG) {
- cnt ++;
- }
- }
- closedir(dir);
- return cnt;
- }
复制代码 来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |