Unix:基础知识文件和目录

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/grassroots2011/article/details/51214185

《Unix环境高级编程》ver3是一部非常不错的书籍,学习中遇到的问题和过程整理记录

实现ls命令实例

Unix——一切皆是文件,文件在Unix环境中是非常重要的东西,Unix文件系统就是一个虚拟层次结构,所有目录都挂载于/根目录,文件夹也可以被认为是一种文件,设备也是一种文件,重要的Socket套接字也是一种文件.

#include "include/apue.h"
#include <dirent.h>

int
main(int argc, char *argv[]){
    DIR     *dp;
    struct dirent *dirp;

    if (argc != 2)
        err_quit("usage: ls directory_name");

    if ((dp = opendir(argv[1])) == NULL)
        err_sys("can`t open %s", argv[1]);

    while ((dirp = readdir(dp)) != NULL) {
        printf("%s\n", dirp->d_name);
    }

    closedir(dp);
    exit(0);
}

运行

cc main.c

报错

Undefined symbols for architecture x86_64:
  "_err_quit", referenced from:
      _main in main-5f8e4b.o
  "_err_sys", referenced from:
      _main in main-5f8e4b.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

缺少err_quit和err_sys的二进制代码
编译器编译成为二进制代码分为四个步骤:

  • 预处理
    预处理过程只是展开宏定义,处理条件编译,展开include指令来插入实际代码和一些杂项工作。
  • 编译
    编译就是将预处理完成的代码进行词法分析、语义分析和代码优化,最终生成相应的汇编代码文件
  • 汇编
    然后就是汇编过程,将其翻译为二进制代码
  • 链接
    链接工作,使用链接器将各个目标文件组装到一起,解决符号依赖等问题,最终形成一个二进制文件,其中还分为链接动态库和静态库的不同。这些阶段都可以指定编译参数来让编译器只执行到某一阶段
> cc -E xxx.c #只执行预处理阶段
> cc -S xxx.c #只执行到编译阶段
> cc -c xxx.c #只执行到汇编阶段

从书的源代码里面找出来,然后使用下面命令将其编译为二进制文件,会生成error.o连接文件

cc -c error.c

使用ar -r liberror.a error.o 将其打包为静态库文件
把liberror.a放到lib文件夹下
把apue.h放到include文件夹下
使用编译命令cc -L./lib -lerror main.c 编译出二进制文件了。
最终生成a.out文件

  • .o 文件
    编译创建用来link的文件
  • .a 文件
    静态类库,已经编译好的库

完成步骤:
1. cc -c error.c 编译成link文件
2. ar -r liberror.a error.o 将error.o打包成静态库文件
3. cc -L./lib -lerror main.c 编译出 a.out 二进制执行文件
4. ./a.out ~/test 测试脚本
输出:

test1
test2
ttttt

opendir()函数:打开目录

头文件:

 include <dirent.h>

定义函数:

DIR * opendir(const char * name);

函数说明:opendir()用来打开参数name 指定的目录, 并返回DIR*形态的目录流, 和open()类似, 接下来对目录的读取和搜索都要使用此返回值.

返回值:成功则返回DIR* 型态的目录流, 打开失败则返回NULL.

错误代码:
1、EACCESS 权限不足。
2、EMFILE 已达到进程可同时打开的文件数上限。
3、ENFILE 已达到系统可同时打开的文件数上限。
4、ENOTDIR 参数name 非真正的目录。
5、ENOENT 参数name 指定的目录不存在, 或是参数name 为一空字符串。
6、ENOMEM 核心内存不足。

上述ls实例中,opendir函数返回指向DIR结构的指针,我们将该指针传递给readdir函数,然后,在循环中调用readdir来读取每个目录项。

猜你喜欢

转载自blog.csdn.net/grassroots2011/article/details/51214185