C语言基础之文件

1,Makefile

意义:解决多文件编译模块化的问题
格式:
main:(目标)main.0 (依赖)
(一个TAB)gcc main.o -o main (命令)
makefile文件名必须为makefile或者Makefile,其余文件名要使用make -f 文件名命令告诉系统去哪找makefile文件

gcc命令:
gcc -c 编译到目标代码,不进行链接 (gcc -c 文件.c 生成 文件.o)
gcc -o <文件> 输出到<文件> (gcc -o 目标文件名.o 文件.o)

Makefile 实例应用

建立一个小项目,有main.c student.c class.c三个文件,
main.c:
C语言基础之文件_第1张图片
class.c:
C语言基础之文件_第2张图片
student.c:
C语言基础之文件_第3张图片
class.h:
这里写图片描述
student.h:
这里写图片描述
此项目实现的功能很简单就是打印10个学生序号
可以使用脚本语言.sh完成
build.sh:
C语言基础之文件_第4张图片
这时,我们使用这个脚本,就能成功编译和链接:
C语言基础之文件_第5张图片
但是,如果文件特别多,在只改动一个文件的情况下,我们不希望全部文件编译,只编译改动文件,这就需要用到Makefile
Makefile:
C语言基础之文件_第6张图片
这时,我们只改动student.c文件,并查看时间戳,makefile执行也是根据时间戳的更改来完成,如果目标晚于依赖文件的时间戳,则执行对应语句:
C语言基础之文件_第7张图片
执行make可以看到,只执行了与student.c文件有关的语句,其余的语句则没有重新编译,大大提高了编译效率

2,静态文件与动态文件

1、静态文件(inode)

硬盘中的文件,就是静态文件。文件都是以多个块和多个扇区组成的。一般情况,一个扇区(512字节),64个扇区组成一个块。在硬盘中,对文件管理有一个特定规则(文件管理表+真实的内容):文件管理表,这个表中是以文件为单位提供了各个文件的所有信息 (每一个文件信息表就对应一个结构体,这个结构体就称之为inode,也叫i节点,这个文件的包含的多少块、多少扇区),而我们通过查找这个表就可以找到我们所需要文件的内容。
我们找文件,通过(文件名字)找的。第一步:在文件管理表中,找到这个文件的名字,第二部,访问这个文件。U盘格式化:1、快速格式化,清除了你的文件管理表,文件系统就找不到你所需要的文件名字 ,你的真实内容还在硬盘里,可以部分恢复 2、彻底格式化,这个就是把文件真实内容也清除掉了,u盘不能通过软件技术恢复了,必须借助国家安全机构(通过物理机制,通过硬件的记忆恢复)。
联系:生活中,处理小文件的一个手段,文件压缩。把扇区的空余字节都利用起来,减少了占用硬盘上的空间。硬盘喜欢大文件。

2、动态文件(vnode)(在内存中)

一个程序的运行就是一个进程,而我们打开的文件就属于这个进程。而操作系统对于每一个进程都有一个结构体进行管理,这个管理当前进程所有信息的结构体,我们就叫做(进程信息表)。这个表中有一个指针指向我们的文件管理表,这个文件管理表就包含了本进程打开的所有文件,通过查找文件管理表的index(文件描述符fd,相当于这个结构体数组的下标),就得到了我们的文件所有信息的结构体(Vnode,V节点),而这个结构体的指针就是文件指针。

3,打印系统时间的小项目

#include 
#include 


int main(void)
{
        //输出型参数
        // time_t time(time_t *t)
        //method 1:
#if 0
        time_t tm;

        time(&tm);

        printf("value of seconds:%lld\n", tm);
#endif
        //返回值
        //method 2:
        time_t t;
//      int  a = 3, *p = &a; 

        t = time(NULL);
        printf("value of seconds:%lld\n", t);

        char *p_time = ctime(&t);

        printf("%s", p_time);

#if 0
                   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 */
                        };
#endif

        struct tm *p_tm = localtime(&t);

        //不判断
        printf("%d-%d-%d %d:%d:%d\n", p_tm->tm_year, p_tm->tm_mon, p_tm->tm_mday, p_tm->tm_hour, p_tm->tm_min, p_tm->tm_sec);

        return 0;
}

4,两个文件描述符来写文件(dup)

#include 
#include 
#include 
#include 
#include 
#include 


int main(void)
{
        int fd = -1;
        close(2);
        //打开一个文件
        fd = open("2.txt", O_RDWR);

        if (fd < 0)
        {
                perror("open");

                exit(0);
        }
        else
                printf("fd = %d.\n", fd);
#if 0
        int fd = -1;
        //打开一个文件
        fd = open("1.txt", O_RDWR | O_CREAT | O_TRUNC, 0666);

        if (fd < 0)
        {
                perror("open");

                exit(0);
        }
        else
                printf("fd = %d.\n", fd);
        //关闭终端输出
        close(1);
        //复制了一个新的fd_new文件描述符,指向1.txt        
        int fd_new = dup(fd);           // 就完成了标准输出的文件重定位,此行开始所有的终端输出都会写在文件里(1.txt)

        if (fd_new < 0)
        {
                perror("dup");

                exit(0);
        }
        else
                //==  写文件
                printf("fd_new = %d.\n", fd_new);
        //对1.txt写操作
        //两个文件描述符,各自操作自己的那份文件,但是两者的读写操作互相影响文件指针,== 多次open加了O_APPEND标志。
        while (1)
        {
                write(fd, "ab", 2);
                sleep(1);
                write(fd_new, "cd", 2);
                sleep(1);
        }
#endif


        return 0;
}

5,模仿ls-l的小程序

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 



int main(void)
{
        //打开一个目录    
        DIR *p_dir = NULL;
        struct dirent *p = NULL;
        struct stat st;

        p_dir = opendir("./");
        //可重入函数和不可重入函数?回去查
        while (p = readdir(p_dir))
        {
                //跳过隐藏文件
                if (*p->d_name == '.')
                        continue;
                memset(&st, 0, sizeof(st));

                stat(p->d_name, &st);
                //类型
                switch (st.st_mode & S_IFMT)
                {
                        case S_IFSOCK:
                                printf("s"); break;
                        case S_IFREG:
                                printf("-"); break;     
                      case S_IFLNK:
                                printf("l"); break;
                        case S_IFBLK:
                                printf("b"); break;
                        case S_IFDIR:
                                printf("d"); break;
                        case S_IFCHR:
                                printf("c"); break;
                        case S_IFIFO:
                                printf("p"); break;
                        default:
                                printf("?"); break;
                }
                //文件权限
        if (st.st_mode & S_IRUSR)   // 真或者假
        {
                printf("r");
        }
        else
                printf("-");

            if (st.st_mode & S_IWUSR)
            {
                    printf("w");
            }
            else
                    printf("-");

            if (st.st_mode & S_IXUSR) 
            {
                    printf("x");
            }
            else
                    printf("-");

            if (st.st_mode & S_IRGRP)   // 真或者假
            {
                    printf("r");
            }
            else
                    printf("-");
            if (st.st_mode & S_IWGRP) 
            {
                    printf("w");
            }
            else
                    printf("-");

            if (st.st_mode & S_IXGRP)
            {
                    printf("x");
            }
            else
                    printf("-");

            if (st.st_mode & S_IROTH)   // 真或者假
            {
                    printf("r");
            }
            else
                    printf("-");

            if (st.st_mode & S_IWOTH) 
            {
                    printf("w");
            }
            else
                    printf("-");

            if (st.st_mode & S_IXOTH) 
            {
                    printf("x");
            }
            else
                    printf("-");

        //hard连接数
        printf(" %d", st.st_nlink);
        //获得use的用户名
        struct passwd *p_uid = NULL;

        p_uid = getpwuid(st.st_uid);

        if (NULL == p_uid)
        {
                perror("getpwuid");

                exit(0);
        }
        //获得group的用户名
        struct group *p_gid = NULL;

        p_gid = getgrgid(st.st_gid);

        if (NULL == p_gid)
        {
                perror("getgrgid");

                exit(0);
        }
        printf(" %s %s", p_uid->pw_name, p_gid->gr_name);
        printf(" %d\n", st.st_size);
}

        return 0;
}

你可能感兴趣的:(技术博客,C语言基础,c语言,makefile,gcc)