zoukankan      html  css  js  c++  java
  • unix环境高级编程-读书笔记与习题解答-第一篇

    从这周开始逐渐的进入学习状态,每天晚上都会坚持写c程序,并且伴随对这本书的深入,希望能写出更高质量的读书笔记和程序。

    本书的第一章,介绍了一些关于unix的基础知识,在这里我不想去讨论linux到底是不是unix或者和unix的关系是什么这样的问题,只针对对自己有价值的知识点进行分析。

    第一节 登录

    第一节中,作者叙述了unix下用户登录的基本过程,包括保存用户口令的文件 /etc/passwd , 以及该文件的格式,该口令文件中的登录项的组成结构为由7个冒号分隔的字符串,依次是 :

    登录名
    加密口令
    用户的数字ID	
    用户的数字组ID	
    注释字段
    用户的起始目录
    用户的shell程序
    
    第二节 文件和目录

    该节的重点是一个目录操作 api 和 unix 目录的组成以及目录的各种属性的说明,另外也说明了unix中组成目录的可用字符,目录操作api,是入门这本教程中的第一个 api, 也是很常用的一个 api, 在笔记的末尾我会综合讨论本章节所使用的所有 api 的细节。

    第三节 输入和输出

    程序就是一个算法,算法的操作资料来源于输入,计算完毕之后就必须输出结果给人类才可以,所以输入输出是很重要的基础内容。

    unix系统使用文件描述符进行文件操作,类似windows中的句柄(至今不明白翻译成句柄是不是为了更加符合中国人的思维),是一个整数,内核通过这个描述符,进行对文件的各种操作,这个描述符对程序员也很重要,我们在得到这个描述符之后,才可以对文件进行相应的操作。

    三个标准文件描述符, 即标准输入,标准输出和错误输出,默认都是终端,由shell默认指配这3个文件描述符,比如 ls 这样的命令, 如果想重定向输出的话, 书中给出了一个简单例子, 就是 使用 > 号, 比如

     ls -al > dir.txt
    

    这样就很简单的把 ls -al 的输出指向到了一个文件里。

    接下来书中讲述了基本的io操作api, 并且提供了示例代码,该示例可以复制任意unix文件, 该程序的分析以及api介绍,会在笔记末尾部分。

    ================================================

    以上章节中所使用的 unix api 解析
    头文件
    #include <dirent.h>
    #include <sys/types.h>
    opendir 原型
    DIR * opendir(const char * path);
    该api 打开一个目录, 打开失败的时候返回 NULL, 目录是文件也会返回NULL, 打开成功则返回一个DIR指针
    
    closedir 原型 
    int closedir(DIR * dir_handle);
    closedir()
    关闭参数dir所指的目录流。关闭成功则返回0,失败返回-1,错误原因存于errno 中。EBADF 参数dir为无效的目录流。
    注意:目录文件作为一种文件,在打开必须关闭,否则会由于文件的进程打开文件过多而不能打开新的文件。因此opendir函数和closedir函数同样是配对出现的。
    
    
    DIR 结构体原型
       
       typedef struct __dirstream DIR;
       struct __dirstream
       {
         void *__fd; /* `struct hurd_fd' pointer for descriptor.   */
         char *__data; /* Directory block.   */
         int __entry_data; /* Entry number `__data' corresponds to.   */
         char *__ptr; /* Current pointer into the block.   */
         int __entry_ptr; /* Entry number `__ptr' corresponds to.   */
         size_t __allocation; /* Space allocated for the block.   */
         size_t __size; /* Total valid data in the block.   */
         __libc_lock_define (, __lock) /* Mutex lock for this structure.   */
        };
        
    DIRENT 结构体原型
    	struct dirent
    	{
    		long d_ino; /* inode number  */
    		off_t d_off; /* offset to this dirent  */
    		unsigned short d_reclen; /* length of this d_name  */		
    		unsigned char d_type; /* the type of d_name  */
    		char d_name [NAME_MAX+1]; /* file name (null-terminated) */
    	}
    

    书中的示例程序

    #include <sys/types.h>
    #include <dirent.h>
    int
    main(int argc, char ** argv)
    {
    	DIR              * dir;
    	struct dirent    * dirt;
    	if(argc != 2)
    	{
    		printf(" you need input a dir name");
    	}
    	if((dp = opendir(argv[1])) == NULL)
    	{
    		printf("can not open %s", argv[1]);
    	}
    	while((dirt = readdir(dir)) != NULL)
    	{
    		printf("%s
    ", dirt->name);
    	}
    	closedir(dir);
    	exit(0)
    }
    

    该示例程序是我改写过了的,没由调用书中的头文件,因为我想构造最短小精悍的可以执行的示例程序,程序非常简单,强行分析的话这个程序是漏洞百出的,不过既然是例子就是越简单越能说明问题越好,该程序从终端获取要去读取的目录,打开成功的话就循环读取目录中的文件并打印出来,非常显而易见的 api 调用方法。

    头文件
    #include <unistd.h>  
    api 原型
    size_t read(int fd, void *buf, size_t count);
    返回值:成功返回读取的字节数,出错返回-1并设置errno,如果在调read之前已到达文件末尾,则这次read返回0
    
    #include <unistd.h>  
    ssize_t write(int fd, const void *buf, size_t count); 
    返回值:成功返回写入的字节数,出错返回-1并设置errno
    

    书中的示例程序

    #include <unistd.h>
    #include <stdio.h>
    #include <stdlib.h>
    #define BUFFSIZE 8192
    int
    main(void)
    {
    	int n;
    	char buf[BUFFSIZE];
    	while((n = read(STDIN_FILENO, buf, BUFFSIZE)) > 0)
    	{
    		if(write(STDOUT_FILENO, buf, n) != n)
    		{
    			printf("write errors");
    		}
    	}
    	if(n < 0)
    	{
    		printf("read error");
    	}
    	return 0;
    }
    

    当你执行该程序生成的二进制文件的时候,发现你输出什么,它就输出什么,该程序循环调用read 然后 直接write 在while中,可以一直循环读写你输入的内容, 所以该程序可以复制任何unix文件。

    gcc -o test ./test.c
    cat test.c > ./test > test1.c
    
    你就会发现你的程序被复制到了test1.c中, 该程序并不是让你把所有的文件打在终端里才会复制,书中的意思是要你使用管道来操作。
    

    决定深入的学习linux编程,所以这周开始学习 unix高级环境编程 这本著作, 做服务器端程序设计的程序员,都需要去学习操作系统, 一个服务是否稳定,是否高效,涉及到很多因素,而操作系统是服务运行的环境,各种系统调用,进程通信,IO模型,socket通信,等等这些都是基础,不精通这些东西是没有办法深入服务器端程序设计的,所以我决定认真学习这本书,同时彻彻底底的把django这个框架分析一遍。

    这是开头,书中的第一章的内容也很简单,所以这篇笔记主要是说学习计划的,如何有效的学习这本书,或者说适合我的这本书的学习计划,应该有一个大概的规划,我已经经历过无数次无头苍蝇般的学习经历了,这么多年,我觉得应该去变化一下方式了,或者是在方法上面动一下脑筋。

    回忆自己以前的学习和工作经历,我的觉悟是,积累是非常重要的,所以更要坚持做笔记,写博客,对于这本书的学习,在一边读的同时,我已经在实践书中的例子程序了,而且我从来不照抄程序,而是完全理解透彻之后,自己查找相应的api,写一个类似书中的程序出来,这样我才能完全理解那些api。

  • 相关阅读:
    localStorage保存账号密码
    作品第二课----简易年历
    作品第二课----滚动列表
    自己遇到的冒泡事件
    Oct 20th-绿叶学习网站总结
    Sep 30th-JavaScript的数组方法总结
    Sep 8th -css sprite
    前端知识体系【转】
    July 27th
    第一节 简单的jsp实例
  • 原文地址:https://www.cnblogs.com/youngershen/p/3999227.html
Copyright © 2011-2022 走看看