zoukankan      html  css  js  c++  java
  • 【转载】Unix设计哲学 & 回车换行八卦 & EOF八卦 & UNIX目录结构八卦

    昨天看了这篇文章 《关于Unix哲学

    首先用了两个例子,用风扇吹出空肥皂盒 和 太空铅笔,来说明简单设计也能派上作用吧。

    Unix哲学,Wikipedia上列出了好几个版本,不同的人有不同的总结。发明管道命令的Doug McIlroy总结了三条,而Eric S. Raymond则在The Art of Unix Programming一书中,一口气总结了17条。

    但是所有人都同意,"简单原则"----尽量用简单的方法解决问题----是"Unix哲学"的根本原则。这也就是著名的KISS(keep it simple, stupid),意思是"保持简单和笨拙"。

    如果你想最简单地完成一项编程任务,我认为可以从四个方面入手:

    1. 清晰原则。
    代码要写得尽量清晰,避免晦涩难懂。清晰的代码不容易崩溃,而且容易理解和维护。重视注释
    不为了性能的一丁点提升,而大幅增加技术的复杂性,因为复杂的技术会使得日后的阅读和维护更加艰难。
    2. 模块原则。 每个程序只做一件事,不要试图在单个程序中完成多个任务。在程序的内部,面向用户的界面(前端)应该与运算机制(后端)分离,因为前端的变化往往快于后端3. 组合原则。 不同的程序之间通过接口相连。接口之间用文本格式进行通信,因为文本格式是最容易处理、最通用的格式
    这就意味着尽量不要使用二进制数据进行通信,不要把二进制内容作为输出和输入。
    4. 优化原则。 在功能实现之前,不要考虑对它优化。最重要的是让一切先能够运行,其次才是效率。

    "先求运行,再求正确,最后求快。"(Make it run, then make it right, then make it fast.)
    90%的功能现在能实现,比100%的功能永远实现不了强。先做出原型,然后找出哪些功能不必实现,那些不用写的代码显然无需优化。目前,最强大的优化工具恐怕是Delete键。

    再来一个 CR和LF的八卦 《回车和换行

    在计算机还没有出现之前,有一种叫做电传打字机(Teletype Model 33)的玩意,每秒钟可以打10个字符。但是它有一个问题,就是打完一行换行的时候,要用去0.2秒,正好可以打两个字符。要是在这0.2秒里面,又有新的字符传过来,那么这个字符将丢失。
    于是,研制人员想了个办法解决这个问题,就是在每行后面加两个表示结束的字符。一个叫做"回车",告诉打字机把打印头定位在左边界;另一个叫做"换行",告诉打字机把纸向下移一行。
    这就是"换行"和"回车"的来历,从它们的英语名字上也可以看出一二。

    后来,计算机发明了,这两个概念也就被般到了计算机上。那时,存储器很贵,一些科学家认为在每行结尾加两个字符太浪费了,加一个就可以。于是,就出现了分歧。

    Unix系统里,每行结尾只有"<换行>",即" ";

    Windows系统里面,每行结尾是"<回车><换行>",即" ";

    Mac系统里,每行结尾是"<回车>"。

    一个直接后果是,Unix/Mac系统下的文件在Windows里打开的话,所有文字会变成一行;而Windows里的文件在Unix/Mac下打开的话,在每行的结尾可能会多出一个^M符号。

    再来一个EOF的八卦(Link

    EOF不是特殊字符,而是一个定义在头文件stdio.h的常量,一般等于-1。

      #define EOF (-1)

    在Linux系统之中,EOF根本不是一个字符,而是当系统读取到文件结尾,所返回的一个信号值(也就是-1)。至于系统怎么知道文件的结尾,资料上说是通过比较文件的长度

    所以,处理文件可以写成下面这样:

      int c;
      while ((c = fgetc(fp)) != EOF) {
        do something
      }

    这样写有一个问题。fgetc()不仅是遇到文件结尾时返回EOF,而且当发生错误时,也会返回EOF。因此,C语言又提供了feof()函数,用来保证确实是到了文件结尾。上面的代码feof()版本的写法就是:

      int c;
      while (!feof(fp)) {
        c = fgetc(fp);
        do something;
      }

    但是,这样写也有问题。fgetc()读取文件的最后一个字符以后,C语言的feof()函数依然返回0,表明没有到达文件结尾;只有当fgetc()向后再读取一个字符(即越过最后一个字符),feof()才会返回一个非零值,表示到达文件结尾。

    所以,按照上面这样写法,如果一个文件含有n个字符,那么while循环的内部操作会运行n+1次。所以,最保险的写法是像下面这样:

      int c = fgetc(fp);
      while (c != EOF) {
        do something;
    
        c = fgetc(fp);
      }
      if (feof(fp)) {
        printf("
     End of file reached.");
      } else {
        printf("
     Something went wrong.");
      }

    EOF还可以表示标准输入的结尾。

      int c;
      while ((c = getchar()) != EOF) {
        putchar(c);
      }

    但是,标准输入与文件不一样,无法事先知道输入的长度,必须手动输入一个字符,表示到达EOF

    Linux中,在新的一行的开头,按下Ctrl-D,就代表EOF(如果在一行的中间按下Ctrl-D,则表示输出"标准输入"的缓存区,所以这时必须按两次Ctrl-D);Windows中,Ctrl-Z表示EOF。(顺便提一句,Linux中按下Ctrl-Z,表示将该进程中断,在后台挂起,用fg命令可以重新切回到前台;按下Ctrl-C表示终止该进程。)

    那么,如果真的想输入Ctrl-D怎么办?这时必须先按下Ctrl-V,然后就可以输入Ctrl-D,系统就不会认为这是EOF信号。Ctrl-V表示按"字面含义"解读下一个输入,要是想按"字面含义"输入Ctrl-V,连续输入两次就行了。

    Unix目录结构的八卦(Link

    Unix(包含Linux)的初学者,常常会很困惑,不明白目录结构的含义何在。

    举例来说,根目录下面有一个子目录/bin,用于存放二进制程序。但是,/usr子目录下面还有/usr/bin,以及/usr/local/bin,也用于存放二进制程序;某些系统甚至还有/opt/bin。它们有何区别?

    一般是根据《Unix文件系统结构标准》(Filesystem Hierarchy Standard),死记硬背不同目录的区别。

    /bin : Essential user command binaries (for use by all users)
    
    /boot : Static files of the boot loader
    
    /dev : Device files
    
    /etc : Host-specific system configuration
    
    /home : User home directories (optional)
    
    /lib : Essential shared libraries and kernel modules
    
    /media : Mount point for removeable media
    
    /mnt : Mount point for a temporarily mounted filesystem
    
    /opt : Add-on application software packages
    
    /root : Home directory for the root user (optional)
    
    /sbin : System binaries
    
    /srv : Data for services provided by this system
    
    /tmp : tmp

    Rob Landley的简短解释,原来Unix目录结构是历史造成的。

    1969年,Ken ThompsonDennis Ritchie在小型机PDP-7上发明了Unix。1971年,他们将主机升级到了PDP-11。当时,他们使用一种叫做RK05的储存盘,一盘的容量大约是1.5MB。

    没过多久,操作系统(根目录)变得越来越大,一块盘已经装不下了。于是,他们加上了第二盘RK05,并且规定第一块盘专门放系统程序,第二块盘专门放用户自己的程序,因此挂载的目录点取名为/usr。也就是说,根目录"/"挂载在第一块盘,"/usr"目录挂载在第二块盘。除此之外,两块盘的目录结构完全相同,第一块盘的目录(/bin, /sbin, /lib, /tmp...)都在/usr目录下重新出现一次。

    后来,第二块盘也满了,他们只好又加了第三盘RK05,挂载的目录点取名为/home,并且规定/usr用于存放用户的程序,/home用于存放用户的数据。

    从此,这种目录结构就延续了下来。随着硬盘容量越来越大,各个目录的含义进一步得到明确。

      /:存放系统程序,也就是At&t开发的Unix程序。

      /usr:存放Unix系统商(比如IBM和HP)开发的程序。

      /usr/local:存放用户自己安装的程序。

      /opt:在某些系统,用于存放第三方厂商开发的程序,所以取名为option,意为"选装"。

    另外关于 /bin 和 /sbin 的区别 (Link

    bin: 
    bin为binary的简写 主要放置一些系统的必备执行档 例如:cat、cp、chmod df、dmesg、gzip、kill、ls、mkdir、more、mount、rm、su、tar等。
    
    /usr/bin:
    主要放置一些应用软体工具的必备执行档 例如c++、g++、gcc、chdrv、diff、dig、du、eject、elm、free、gnome*、 gzip、htpasswd、kfm、ktop、last、less、locale、m4、make、man、mcopy、ncftp、 newaliases、nslookup passwd、quota、smb*、wget等。 
    
    /sbin: 
    主要放置一些系统管理的必备程式 例如:cfdisk、dhcpcd、dump、e2fsck、fdisk、halt、ifconfig、ifup、 ifdown、init、insmod、lilo、lsmod、mke2fs、modprobe、quotacheck、reboot、rmmod、 runlevel、shutdown等。
    
    /usr/sbin:
    
    放置一些网路管理的必备程式例如:dhcpd、httpd、imap、in.*d、inetd、lpd、named、netconfig、nmbd、samba、sendmail、squid、swap、tcpd、tcpdump等

    云主机

    另一篇云主机的文章中(Link),我觉得下面这句比较有道理:

    如果你想把钱藏在安全的地方,请问你是选择家中床垫下面,还是选择银行?这个比喻对服务器管理的方方面面都适用,不仅是安全性,还包括正常运行时间带宽负载管理备份等等,都是我们占优。

  • 相关阅读:
    Squeeze-and-Attention Networks for Semantic Segmentation
    重装电脑系统(用山寨优盘)
    TensorFlow会话常用的两种方式
    Towards Learning Structure via Consensus for Face Segmentation and Parsing
    什么是feature map(个人理解)
    Fatal error in launcher: Unable to create process using '"d:downloadpython.exe" "D:downloadScriptspip.exe" list': ???????????
    JS :函数
    JS之继承
    原型模式
    面向对象之工厂模式和构造函数模式
  • 原文地址:https://www.cnblogs.com/charlesblc/p/6134244.html
Copyright © 2011-2022 走看看