IO目录操作及库的制作(Linux c语言)

今天我们接着前一篇的内容来谈一谈IO的目录操作:跟前面的文件操作一样,还是通过相对应的函数来对目录文件进行操作,下面进行相关函数的详细介绍。

一、目录操作

1、打开目录 -- opendir()

       #include <sys/types.h>
       #include <dirent.h>

       DIR *opendir(const char *name);
	参数:
        name:目录流指针
	返回值:
        成功返回目录流指针,失败返回NULL

2、读取目录 -- readdir()

这个函数要注意的是:  readdir一次只能随机读取一个目录项

       #include <dirent.h>

       struct dirent *readdir(DIR *dirp);

结构体:
struct dirent {
               char           d_name[256]; /* Null-terminated filename */   //文件名
              };

 

3、关闭目录 -- closedir()

       #include <sys/types.h>

       #include <dirent.h>

       int closedir(DIR *dirp);
	
	参数:
        dirp:关闭目录流指针
    返回值:
        成功返回0,失败返回-1

 

4、获取文件属性 -- lstat()

       #include <sys/types.h>
       #include <sys/stat.h>
       #include <unistd.h>

       int stat(const char *pathname, struct stat *statbuf);
       int fstat(int fd, struct stat *statbuf);
       int lstat(const char *pathname, struct stat *statbuf);
参数:
   pathname:文件名 
   statbuf:存放文件信息的结构体指针
返回值:
    成功返回0,失败返回-1;
    
    struct stat
    {
               mode_t    st_mode;        //文件类型和权限
               nlink_t   st_nlink;       //文件硬链接数
               uid_t     st_uid;         //用户ID
               gid_t     st_gid;         //用户组ID
               off_t     st_size;        //文件大小
               struct timespec st_mtim;  //最后修改文件时间

           	   #define st_mtime st_mtim.tv_sec
	}
	

好了,相关知识点就到这里,学完上面的内容,我们可以一个小练习来巩固所学

练习:用函数完成 ls -l 命令的制作

首先我们的知道ls -l命令的内容如下图:

 下面是需要用到的一些函数:

用到的相关函数:
    
	获取文件类型:
        S_IFMT     0170000   bit mask for the file type bit field
           S_IFSOCK   0140000   socket
           S_IFLNK    0120000   symbolic link
           S_IFREG    0100000   regular file
           S_IFBLK    0060000   block device
           S_IFDIR    0040000   directory
           S_IFCHR    0020000   character device
           S_IFIFO    0010000   FIFO
	
			如果 st_mode & S_IFMT等于对应文件类型宏,则文件类型宏对应类型就为文件类型
	
	获取文件权限:
		st_mode & 对应权限宏 == 宏本身 表示具有该权限

		   S_IRUSR     00400   owner has read permission
           S_IWUSR     00200   owner has write permission
           S_IXUSR     00100   owner has execute permission

	       S_IRGRP     00040   group has read permission
           S_IWGRP     00020   group has write permission
           S_IXGRP     00010   group has execute permission
	
		   S_IROTH     00004   others have read permission
           S_IWOTH     00002   others have write permission
           S_IXOTH     00001   others have execute permission
    
    
    localtime--得到时间戳     
       #include <time.h>

       struct tm *localtime(const time_t *timep);

结构体:
struct tm {
               int tm_sec;    /* Seconds (0-60) */
               int tm_min;    /* Minutes (0-59) */
               int tm_hour;   /* Hours (0-23) */
               int tm_mday;   /* Day of the month (1-31) */
               int tm_mon;    /* Month (0-11) */
               int tm_year;   /* Year - 1900 */
               int tm_wday;   /* Day of the week (0-6, Sunday = 0) */
               int tm_yday;   /* Day in the year (0-365, 1 Jan = 0) */
               int tm_isdst;  /* Daylight saving time */
           };



       getgrgid -- 得到用户组名的函数
       			#include <sys/types.h>
       			#include <grp.h>

       			struct group *getgrgid(gid_t gid);

                struct group 
                {
               		char   *gr_name;        /* group name */
             
          		};


	   
       getpwuid -- 得到用户名的函数
           		#include <sys/types.h>
                #include <pwd.h>

               struct passwd *getpwuid(uid_t uid);

              struct passwd 
              {
                   char   *pw_name;       /* username */
              };

代码实现:

#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
#include <time.h>
#include <unistd.h>
#include <sys/stat.h>
#include <grp.h>
#include <pwd.h>

int main(int argc, char *argv[])
{ 
    int ret = 0;
    int i  = 0;
    int x = 1;
    struct stat info;    //创建存放文件信息的结构体
    struct tm *t = NULL;   //存放时间信息的结构体
    struct group *gp = NULL;   //存放用户组信息的结构体
    struct passwd *usr = NULL;  //存放用户信息的结构体

    DIR *dir = opendir(".");   //打开目录得到目录流指针
    if(NULL == dir)
    {
        perror("opendir");
        return -1;
    }

    struct dirent *buf = NULL;    

    while( (buf = readdir(dir)) != NULL)   //循环遍历目录得到每一个目录项
    {
        if(buf->d_name[0] != '.')    //不显示隐藏文件
        {
            
            ret = lstat(buf->d_name, &info);   //通过文件名得到文件信息
            if(ret < 0)
            {
                perror("lstat");
                return -1;
            }
            		
           	switch(info.st_mode & S_IFMT)
           	{
           		case S_IFREG:
           			printf("-");   break;
           		case S_IFDIR:
           			printf("d");   break;
           	}
           
           	for(i = 8; i >= 0; i--)
           	{
           		if(info.st_mode & (x<<i)) //这里通过观察规律,可以用位移来做,代码比较简洁
           		{
           			switch(i%3)
           			{
           				case 2:
           					printf("r");  break;
           				case 1:
           					printf("w");  break;
           				case 0:
           					printf("x");  break;
           			}
           		}
           		else
           		{
           			printf("-");
           		}
           	}
			
			printf("  %ld  ", info.st_nlink);  //打印硬链接数
			
			usr = getpwuid(info.st_uid);
			printf("%s  ", usr->pw_name);    //打印用户名
			
			gp = getgrgid(info.st_gid);
			printf("%s  ", gp->gr_name);     //打印用户组名
			
			
			printf("%-8ld ", info.st_size);  //打印文件大小
			
			t = localtime(&info.st_mtime);
			printf("%d月  %d  %02d:%02d  ", t->tm_mon, t->tm_mday, t->tm_hour, t->tm_min);                                    //打印最后一次修改文件时间

            printf("%s\n", buf->d_name);      //打印文件名
        }
    }


    closedir(dir);
    return 0;
} 

运行结果:

 二、库的制作

库的本质:二进制文件

库的类型:静态库和动态库(共享库)

静态库和动态库的区别在于加载程序的时机不同

1、静态库

在程序编译阶段(链接阶段),将库的代码加以复制拷贝的方式加载到源程序中

特点:

1、占资源空间,文件体积大

2、运行时,不需要静态库存在

3、可移植性强

4、优化升级时,需要重新编译源文件

静态库制作流程:

1、先预留接口函数
2、实现所有函数功能
3、生成所有的.c文件的目标文件(以.o结尾的文件)
4、编译生成静态库
    ar crs

静态库文件的命名规范:

以lib开头,以.a结尾,中间为库名

libhello.a --> libhello.a==库文件名

hello==库名

链接静态库:

gcc man.c -L. -lhello

 

2、动态库

在程序编译阶段,只是将需要用到的函数做一个记录,最后在程序运行阶段再加载需要用到的函数

特点:

1、不占资源空间,编译之后可执行文件比较小

2、运行时需要动态库存在

3、可移植性差

4、优化升级比较方便,不需要重新编译源文件

动态库的制作流程:

1、先预留接口函数
2、实现所有函数功能
3、将所有的.c文件生成对应的目标文件
    gcc -c -fPIC hello.c -o hello.o
    -fPIC --表示生成位置无关代码
4、编译生成动态库
    gcc -shared -o libhello.so hello.o

动态库文件的命名规范:

以lib开头,以.a结尾,中间为库名

libhello.a --> libhello.a==库文件名

hello==库名

链接动态库:

gcc man.c -L. -lhello

  • 5
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值