linux:

2017_10_21:

1.  shell :unix系统
    bash(伯恩为了linux系统重写的shell的缩写): linux系统

    shell命令:
    终端中敲入可以运行的正确命令。
    shell命令解释器。
    对应的命令-》对应的操作。

2. linux快捷键:

    1>.history :我所用过的命令
        结合ctrl+p(从下往上),结合ctrl+n(从上往下);

    2>.光标移动 
            ctrl+b:向前移动
            ctrl+f:向后移动
            ctrl+a:移动到行首
            ctrl+e:移动到行尾
            ctrl+u: 删除光标前面的字符
            ctrl+d: 删除光标后面的字符


3.linux系统目录结构:
        没有盘符结构,是一种树结构。

        1>.根目录 ;
        2>./bin :  binary 的缩写,这个目录存放着经常使用的命令:cp,mv,date等。
                因为配置了环境变量,敲入命令,命令解释器就会到这个目录下面来找。

        3>./boot : 这里存放的是启动linux时使用的一些核心文件,包括一些连接文件和镜像文件;

        4>./dev  : dev是device 的缩写,该目录下存放的是linux的外部设备,
            在linux中访问设备的方式和访问文件的方式是相同的。

        5>./etc : 这个目录用来存放所有的系统管理所需要的配置文件和子目录

        6>./home : 当前环境中有多少个普通用户,各是什么?显示各自的用户目录。


        7>. /lib  : 这个目录存放着系统最基本的动态链接共享库,起作用类似于
                windows里的dll文件,几乎所有的应用程序都需要用到这些共享库。


        8>. /media : linux系统会自动识别一些设备,例如U盘,光驱等 ,当识别后,
                linux会把自动识别的设备挂载到这个目录下。


        9>. /mnt : 系统提供该目录是为了让用户临时挂载别的文件系统的,
                我们可以把光驱挂载在/mnt/上,然后进入该目录就可以查看
                光驱里的内容了。


        10>. /opt : 这是给主机额外安装软件所存放的目录,比如你安装一个
                oracle数据库 时就可以放到这个目录下,默认是空的。

        11>. /proc :  这个目录是一个虚拟的目录,它是系统内存的映射,我们可以
                    直接访问这个目录来获取系统信息,这个目录的内容不是在硬盘
                    上而是在内存里,我们也可以直接修改里面的某些文件。


        12>. /root : 该目录为系统管理员,也称为超级权限者的用户主目录。


        13>. /sbin : s就是super user 的意思,这里存放的是系统管理员使用
                    的系统管理程序。


        14>. /usr  : 这是一个非常重要的目录,用户的很多应用程序和文件都
                    放在这个目录下,类似于windows下的program files目录。





4.用户目录:
        1>. 绝对路径 :  从根目录开始写 :/home/itcast/aa
        2>. 相对路径 :
                .  -> 当前目录简写
                .. -> 当前的上一级目录简写
                cd -  :在邻近的两个目录中切换
                cd ~  :跳到当前的用户目录。

        3>. itcast@ubuntu:$
                itcast:当前 登录用户
                @:at 在
                ubuntu:主机名
                $: 普通用户
                #: root用户




5. 文件和目录操作:

        1>. 查看我的资产(目录);
        2>. 查看文件内容:
            cat:查看几十行以内的文件内容;
            more:回车一行的看,空格翻页看。不能往前翻页。
                退出按Q键或ctrl +c。

            less:回车一行的看,空格翻页操作,ctrl+p一行一行
                往前翻,ctrl+b往前翻页。(简单了解,不经常用)


            head:默认显示文件 前十行
                自定义 :head -5 [文件名],查看文件前5行。

            tail:默认显示文件 后十行


6.创建软链接,相当于创建了一个快捷方式。
        例如: ln -s hello.c  hello.soft
            此处要注意创建链接的对象要使用绝对路径,这样
            之后随便移动软链接的位置,都可以用。



7.创建硬链接,相当于一份备份。
        注意,原理上并没有发生拷贝,因为硬链接并不占据磁盘空间。
        *linux文件系统的存储单元是块。
        原理自己去查,inode结点保存文件信息。



8.文件或目录属性:
        1>.wc  获取一个文本文件的信息。
        2>.od 查看二进制文件。 
        3>.du -h    显示当前目录下所有文件的大小。
        4>.df -h    显示当前磁盘情况。           

        5>.which ls  显示/bin/ls
                      对应的命令所在的路径。

                    对內建命令,如cd无法查看。

8.
        查看当前登录用户:whoami
        修改文件权限:

            1.文字设定法:chmod [who] [+|-|=] [mode]
                who:
                    文件所有者 :u
                    文件所属组 :g
                    其他人 : od
                    +:添加权限
                    -:减少权限
                    =:覆盖原来的权限
                    mode:
                        r:读
                        w:写
                        x:执行


            2.数字设定法:

                    chmod 777 laowang


9.改变所属用户,改变所在组:

        1.chown  yinghuoai laowang  改变文件老王的所属用户为yinghuoai
        2.chown  yinghuoai:yinghuoai  laowang  “:”前面是所属用户,后面为所在组,都为yinghuoai
        3.chgrp yinghuoai laowang  改变所在组:
         前提:都得加sudo。

        为什么要这样:chmod 777 太暴力了!!!


        目录 必须有执行权限,这样我们才可以进去!!!


10.查找文件:
            1.按文件名查找:
                    find ~/  -name filename
            2.按文件大小查找:
                    find ~/  -size  -10M  -size  +10k

            3.按文件类型查找:
                    find ~/  -type f
                    查找普通文件
                    find ~/  -type p
                    查找管道文件

11.文件的检索:

            1.查找文件里的字符串:
              grep


12.U盘的挂载:
        插上U盘,自动挂载到/media目录;
        先卸载,sudo umount /media/ubuntu/ESD-ISO  卸载什么 ,参数是一个
        然后挂载到/mnt 目录:
            但是首先得得知设备的名字:
                sudo fdisk -l
        然后挂载:sudo mount /dev/sdb4 /mnt  把什么挂载到哪里,两个参数

        所有怎么拿出去呢,cp 就行了


        注意,不能在/mnt卸载,需要跳到其他目录再卸载。
        其实也可以挂载到其他目录下,但是挂载的过程会覆盖 原有de
        内容,所以最好是一个空目录。

13.压缩包管理:

        gzip:--.gz格式压缩包
        bzip2:--.bz2格式压缩包


        1.tar:
                参数:
                    c--创建--压缩;
                    x--释放--解压缩;
                    v--显示提示信息--压缩解压缩--可以省略
                    f--指定压缩文件的名字
                    z--使用gzip的方式压缩文件--.gz
                    j--使用bizp2的方式压缩文件--.bz2

                压缩:
                    tar zcvf 生成的压缩包的名字(xxx.tar.gz) 要压缩的文件或目录
                    tar jcvf 生成的压缩包的名字(xxx.tar.bz2) 要压缩的文件或目录

                    把什么东西压缩成什么东西,需要两个参数

                解压缩:

                    tar zxvf 要解压的文件(默认解压到当前文件)

                    还可以解压到指定目录:

                    tar jxvf 要解压的文件名 -C 解压到的目录

                    把什么东西解压到什么位置,两个参数,默认解压到当前文件夹 。

        2.rar--必须手动安装该软件:

                参数: 

                    压缩: a
                    解压缩: x

                压缩: 
                    rar a 生成的压缩文件的名字(temp) 压缩的文件或目录

                解压缩:
                    rar x 压缩文件名 解压缩目录






        tty1-tty6:文字终端
        tty7:桌面终端。


14.进程操作:
        ps: 
            ps a
            打印当前所有用户的信息

            ps au
            更加丰富化的信息

            ps aux
            查看没有终端的进程信息(会显示大量内容)


            此时,可以使用管道进行重定向 ,其实就是过滤信息的作用。

            指令1 | 指令2

            指令1的输出作为指令2的输入,最终的处理结果才会显示
            在屏幕上。


            例如:ps aux | grep bash

            就是ps aux 中的结果中 有bash 的信息

            终端的作用,有无的影响。带终端,是为了和用户进行
            交互的。没有,也就是不需要与用户交互。

            每一个进程对应一个bash。


        kill:
            kill -l
            显示kill 参数可选项,查看所有的信号

            选择第9号杀死进程
            kill -SIGKILL 进程的PID



15.环境变量:
            env:打印当前进程下的所有环境变量

            环境变量格式:key value值:
                    key = value1:value2:value3

                    如PATH=/usr/bin


            top:
                相当于linux下的任务管理器,但是只能看。
                ctrl+c--关闭。



16.ping 

            linux: ifconfig 查看mac地址和ip地址。
            ping ip地址  -c 4
            链接4次就停下。


            windows:ipconfig


            如何得知域名对应的IP地址?
            用nslookup :
                nslookup www.baidu.com



17.ubuntu 下的用户管理:

            添加用户:
                1.sudo adduser + 用户名
                    addusr 是个脚本,所以比较简单
                    但是当用户名有大写字母的时候,就不能用adduser了。


                2.useradd 
                    useradd 是个命令,较为复杂
                    sudo useradd -s /bin/bash  -g Robin -d /home/Robin -m Robin
                                 用到的shell    用到的组     


                3.修改root用户的密码:
                        sudo passwd (root) 
                        root 可有可无



                4.deluser
                        sudo deluser 用户名


                5.userdel



18.ftp服务器的搭建:  --vsftpd
                作用:单一,负责文件的上传和下载。


                1.服务器端:
                    1.修改配置文件--如何修改配置文件
                        cd /etc
                        ls -l vsftpd.conf

                        sudo gedit vsftpd.conf

                        修改vsftpd.conf文件内容,
                        取消相关注释,并且使能相关设定。



                    2.重启服务--什么命令能够重启服务

                        sudo service vsftpd restart


                2.客户端:
                    1.实名用户登录
                        ftp+IP(server)
                        输入用户名(server)
                        输入密码

                        文件的上传和下载 ,都是在客户端上输命令。,不允许操作目录,
                        如果想操作目录,只能压缩打包。


                            上传: put filename  
                                上传的文件可以是登录之前,客户端的pwd

                            注意,上传的时候,两边的两个目录要搞清楚。   


                            下载:

                                get filename 
                                    文件的下载。


                    2.匿名用户登录,用到的时候最多。

                            ftp+serverIP
                            用户名:anonymous
                            密码:直接回车。


                            创建了一个myftp 文件夹,我建在了用户目录下。
                            还需要修改  /etc/vsftpd.conf
                            指明这个文件夹为匿名用户ftp服务文件夹。



                    3.lftp客户端访问ftp服务器,相当于一个小工具

                            软件安装:sudo apt-get install lftp
                            然后就可以用了

                            lftp ip地址

                            输入“login”

                            put 上传文件
                            mput 上传多个文件
                            get 下载文件
                            mget 下载多个文件
                            mirror 下载整个目录及其子目录
                            mirror -R 上传整个目录及其子目录




19.nfs服务器的搭建:

            作用:net file system 网络文件系统,它允许
            网络中的计算机之间通过tcp/ip网络共享资源 。

            1.安装软件:
                sudo apt-get install nfs-kernel-server

            2.创建一个欲共享出去的目录:
                如: /home/xxx/xxx

            3.打开配置文件:
                sudo vi /etc/exports

            4.写入共享目录的绝对路径,及对应权限
                如:/home/ubuntu/ubuntu


            、、、、、、、、、、、、、、、、

            1.服务器端: 
                1.创建共享目录
                    mkdir dir 
                2.修改配置文件
                    /etc/exports
                3.重启服务
                    sudo service nfs-kernel-server restart




            2.客户端:  
                1.挂载服务器共享目录 

                    sudo mount serverIP:sharedir  /mnt


20.ssh服务器:
        什么时候用?
            其实我最经常用到的是用树莓派的时候。
        无论何时何地,可以远程地对服务器进行操作。

        sudo apt-get install spenssh-server


        运用:
            ssh ubuntu@192.168.1.109

            ssh 用户名@ip地址
            输入 yes.


            退出:logout


        scp命令:
                super copy
                可以在不同的主机间进行拷贝。
                scp -r 目标文件名@目标主机IP地址:/目标文件的绝对路径  /保存到本机的绝对(相对)路径

                拷贝目录需要加参数-r

linux 下切换7个终端:ctrl+alt +F1~F7,各个终端之间是互不影响的。

21.man和echo
        man man

        echo "hello linux"

        查看当前的环境变量

        env | grep PATH

        echo $PATH

        PATH:key-value 值,使用$就可以从变量中取值。



22.vi和vim
        vim是vi发展过来的一款 文本编辑器。

        三种工作模式:
            1.命令模式:
                打开文件之后,默认进入

            2.编辑模式:
                需要一些命令,切换到这种模式。

            3.末行模式:



        光标的移动:
            H:向前  J:向下 K:向上 L:向后

            0:光标移动到行首
            $:光标移动到行尾
            gg: 把光标移动到当前文本文件的开始位置。
            G:把光标移动到当前文本的末尾位置。

            500G:光标移动到第500行。

            x:删除光标后面的一个字符

            X:删除光标前面的一个字符

            u:撤回  ,undo

            dw:删除光标当前的字符串,一个单词。

            d0:删除光标之前的内容

            D:删除光标之后的所有内容

            dd:删除光标所在的行。



            4dd:删除4行。


            vim中“删除”并不是真正的删除,而是剪切。



            p:粘贴到光标所在行下面

            P:粘贴到光标所在行



            yy:复制

            v:切换到可视模式
                对于选中的内容
                y:复制
                d:删除


            /stdio.h:
                查找“stdio.h”
                从光标开始向下查找,并返回头部。


            ?stdio.h:
                查找“stdio
                从光标开始向上查找,顶部之后,返回到尾部。

            遍历时候的快捷键:
                N/n



            切换到文本模式的操作:

                    a-- 在光标所在位置的后边插入
                    A-- 在当前行的尾部插入

                    i-- 在光标所在位置的前边插入
                    I-- 在光标所在行的行首插入

                    o-- 在光标所在行的下边开辟一个新的行
                    O-- 。。。。。。。。。上。。。。。

                    s-- 删除光标后边的字符



            末行模式:
                输入 
                :300  
                跳转到300行。

                进行字符串的替换   :  替换光标所在行的第一个tom, 
                :s/tom/jack

                替换当前行的所有内容
                :s/tom/jack/g

                替换当前文件中的所有tom
                :%s/tom/jack/g


                替换其中某几行的tom
                :27,30s/tom/jack/g

                执行其他命令:
                :!ls

                水平分屏:
                :sp

                两个屏之间切换:

                ctrl+w+w


                保存所有的分屏:
                :xall

                垂直分屏:
                :vsp


                两个屏之间切换:

                ctrl+w+w


                !!可以用vim打造IDE













23.gcc 编译器:

        gcc hello.c -I ./inclue  -o hello

        自定义的头文件存放的绝对路径。

        -I ./include 

        在gcc编译的时候添加include 路径。


        -D DEBUG 
        在gcc 编译的时候添加宏DEBUG ;



        -O(0/1/2/3)

        在gcc编译的时候优化等级,0不优化,3最高等级优化。


        -Wall
        在gcc编译的时候输出警告信息。


        -g
        在gcc编译的时候,添加调试信息,用于gdb调试。


24.静态库

        1.命名规则:
            1.lib+库的名字+.a
            2.libmytest.a
        2.制作步骤:
            1.生成对应的.o文件  
            -c
            2.将生成的.o文件打包 
            ar rcs + 静态库的名字(libmytest.a) + 生成的所有.o文件

        3.发布和使用静态库:
            1>.发布静态库
            2>.头文件

            也就是给用户发送
            include目录和lib目录的文件

        4.优缺点:


            总结,最后怎么用呢?
            一个总文件夹 all;
                它包括3个文件夹,1个文件
                3个文件夹分别是Lib文件夹,src文件夹,include文件夹
                1个文件是main.c文件

                    lib文件夹存放  libmytest.a 之类的lib库文件 ,
                        这些库文件由src文件夹中对应的源文件编译生成
                        的*.o文件打包生成

                    src文件夹存放  add.c sub.c mul.c div.c 之类的子函数源程序

                    include文件夹存放  “head.h”之类的头文件。


            最终使用:

                举例:
                    假设我们所处的目录就是all文件夹目录:

                    gcc main.c lib/libmycalc.a -o sum -I ./include/

                    或者

                    gcc main.c -I include  -L lib -l mycalc -o sum



                    其中-L:指定所有库的路径
                    -l:指定具体用到的库的名字。



                    最终执行:
                    ./sum



            nm libmycalc.a:

            查看静态库中的内容



            nm sum:

            查看可执行文件的内容。
                T--在代码区



            注意,使用静态库的时候,打包的最小单位其实是*.o文件
            我们要知道,*.a文件里有多个*.o文件,*.o文件里有多个
            函数,我们在主程序中用到了哪些函数,也就是编译生成的
            执行程序就把相应函数所在的*.o文件打包进去,也就是并不是一股脑
            将*.a文件打包进去,切记。

            如何验证呢?
            用nm 命令。


        静态库的优点:
            1.发布程序的时候,不需要提供对应的库;
            2.加载库的时候速度很快;

        静态库的缺点:
            1.库被打包到应用程序中,导致应用程序的体积很大。
            2.如果库发生了改变 ,需要重新编译程序。




25.动态库,共享库

        1.命名规则:
            lib+名字+.so

        2.制作步骤:
            1.生成与位置无关的代码,(生成与位置无关的*.o文件)
            gcc -fPIC -c *.o -I ../include


            每一个应用程序执行起来时候,都会对应地分配一个虚拟
            地址空间,虚拟地址空间在虚拟内存中,虚拟内存占用
            硬盘的空间。针对32位操作系统,每个程序运行起来都会
            分配一个0~4G的虚拟地址空间。

            大致分:受保护区,代码段,已初始化全局变量区,
            未初始化全局变量区,堆空间,共享库,栈空间,环境变量
            ,linux kernel (高地址1G)

            *.o文件在打包生成的时候如果附加了绝对地址信息,也就是
            如果调用到对应的*.o文件的时候,都会把它的程序放在
            一个固定的位置。这是静态库。这就叫与代码有关。


            而动态库在打包的时候,*.o不会被打包到可执行程序中
            ,只是做了符号的记录。
            当程序执行之后,才开始加载动态库。
            也就是把对应的*.o文件加载到虚拟地址的
            共享库区域 。


            然后怎么查找呢?采用相对地址的形式,就是偏移地址。
            相对谁偏移呢?
            就是相对程序加载到共享库区域的地址,加上语句在程序
            中的偏移。



            另外的话,共享库区域,还包括c标准库和
            linux 直接IO函数。




            2.将*.o文件打包生成*.so 文件。

            gcc -shared -o libmycalc.so -I ../include 

            mv libmycalc.so ../lib


            使用动态库:

                1.gcc main.c lib/libmycalc.so -o sum -I include

                或者

                2.gcc main.c -I include -L ./lib -l mycalc -o sum


            注意,用-l的时候要把lib库的名字掐头去尾。

            ldd 
            例如: ldd sum
            命令查看,
            执行程序过程中所有依赖的动态库。


            如果不能动态链接,后面会显示not found



            注意,其中动态链接器程序帮助我们把对应的动态库
            加载到应用程序中的。

            动态链接器 ld-linux-x86-64.so.2
            根据一个规则进行查找
            什么规则呢?
            就是环境变量。
            哪个环境变量呢 ?
                echo $PATH
                查看。
            动态库的环境变量又与此不同。
            是另外的环境变量。



            最终执行程序的时候出现错误,显示动态加载共享库失败。
            怎么办呢?
            解决方法:
            改变LD_LIBRARY_PATH 环境变量的值。

            export LD_LIBRARY_PATH=./lib


            这样就解决了。

            但是,这种方法只是临时性的。
            所以,仅适用于开发过程中,临时导入作用。


            那么怎么实现库的导入的永久设置呢?

            写入当前用户的bash文件。


            虚拟终端每次重新打开的时候,都会重新
            读取一下.bashrc文件中的配置。也就是会更新
            一下。


            第4中方案,比较重要,也比较复杂:
                1.需要找到动态连接器的配置文件;
                2.冬天库的路径写到配置文件中;
                3.更新--sudo ldconfig -v

                -v:显示信息的输出。


            举例:
                cd /etc

                ls -l ld.so.conf

                vim ld.so.conf

                添加

                对应的动态库目录
                /home/ubuntu/aa/xin/lib








            总结一下,4种方法:
                1.放到系统的根目录中,---不允许使用
                2.临时测试
                    环境变量:LD_LIBRARY_PATH=将动态库的路径设置
                    将设置的值导入 系统环境变量。
                    当终端关闭,设置会失败。

                3.不常用方法(永久设置)
                    在家目录的.bashrc文件中 添加一句话:
                        export LD_LIBRARY_PATH=动态库目录绝对路径
                    需要之后重启终端。


                4.
                    1.需要找到动态链接器的配置文件
                        /etc/ld.so.donf

                    2.动态库的路径写到配置文件中--绝对路径

                    3.更新--sudo ldconfig -v





                动态库的优点:
                    1.执行程序体积小
                    2.动态库更新了,不需要重新编译程序
                        前提是函数的接口没有发生变化。

                动态库的缺点:
                    1.发布程序的时候,需要将动态库提供给用户
                    2.动态库没有被打包到应用程序中,加载速度
                    相对较慢。




26.gdb调试:


            一个程序工程是包含多个程序文件的。
            l 命令。
            只会列出包含main函数的文件内容

            如果我们想看其他文件的内容呢?或者调试其他文件呢?
            比如说,想看sort.c文件 。

            l sort.c:20

            这样就会把sort.c文件中20行上下5行的内容列出来。

            还有其他用法:

            l sort.c:selection

            这样就会把sort.c文件中selection函数周围10行的程序内容列出来。


            比如一个for中。
            i从0开始,到100
            我们想在i=50的时候,让程序停下,
            这个叫条件断点。

            b 15 if i==15

            其中15是程序中for语句内部的第一句所在的行号,
            不然是不会挺的。注意!!!

            b 行号


            b 函数名:行号

            以上几种设置断点的方法。




            i b

            查看断点信息


            start

            程序开始执行,且只执行一步


            n

            单步执行

            c

            继续执行直到断点。


            s

            进入到函数内部。



            p(print) 变量名

            查看对应的变量的值


            ptype 变量名

            查看对应的变量的类型。


            比如一个for循环中i,j都在改变
            我们每次单步运行的时候想要自动显示出i,j的变化情况,也就是追踪变量值。


            可以在这之前
            display i

            dispaly j 

            之后再 n的时候,就会自动打印了。



            取消追踪用:

            undisplay 编号

            编号如何获取呢?


            info dispaly

            查看获得。


            u 
            跳出单次循环


            finish 
            跳出所在函数。


            d(delete) 编号

            删除断点,通过相应的编号


            怎么获取断点编号呢?
            同样的,
            i b


            for循环中i通常是个累加量

            如何能够自己在gdb中直接设置
            i=10呢?


            set val i=10

            r(run)
            另一种运行程序的方法


            所以,注意,使用gdb其他功能之前,先把断点打上。




27.makefile

            1.makefile的命名:
                makefile 或者Makefile


            2.编写makefile
                vim makefile

                规则:
                3要素:目标、依赖条件、命令。
                    目标:依赖条件
                        命令


                        如果不存在就向下查找。


            3.变量:

                obj=main.o add.o sub.o mul.o
                target=sum 

                $(target):$(obj)
                    gcc $(obj) -o $(target)


                之后还有一句比较特殊的:
                涉及到模式匹配。 也就是 之前的 main.o add.o sub.o mul.o--
                中的.o前面的字符都会自动匹配。下面的语句。

                %.o:%.c
                    gcc -c $< -o $@


                什么是$< ?什么是$@呢?

                makefile 中的自动变量。
                $<:规则中的第一个依赖。
                $@:规则中的目标。
                $^:规则中的所有依赖,即变量obj。

                要求:
                    自动变量只能在规则的命令中使用 。



                makefile中提供的函数,所有的函数都是有返回值的。
                而返回值的获取也是需要$符号。

                makefile中函数的使用:
                比如:

                src=$(wildcard  ./*.c )                    
                obj=$(patsubst  ./%.o, ./%.c, $(src))         匹配替换函数,用的是模式匹配,不是*

                如果加一个额外语句:

                clean:
                    rm $(obj) $(target) -f

                这条命令没有依赖,
                当我们在外面
                make clean 时,就只执行这条语句,只生成clean
                ,其他的语句都没有执行,也就是最终的目标sum
                也没有生成。

                -f
                强制执行。


                在命令之前加“-”,就是如果这条命令执行失败了
                ,就忽略掉这条命令,继续向下执行

                如:
                -mkdir aa


28.c库函数

            c库函数提供了一个io缓冲区。为什么呢?
            因为我们读的文件是磁盘文件,
            磁盘都是机械硬盘,读取速度是ms级别
            内存读取速度是ns级别
            两者相差一百万倍。




            FILE* fp;

            fp指向了一个结构体
            结构体里面有  文件描述符 -》索引到对应的磁盘文件,比如hello.txt
                          文件读写指针位置 -》 读写过程中指针的实际位置,比如hello.txt 中第10行
                                当前文件指针位置,通过fseek()函数操作。
                          I/O缓冲区(内存地址) -》 通过寻址找到对应的内存块。


            数据从内存缓存中的数据刷新到磁盘上:
                    1.刷新缓冲区:fflush
                        强制性地把缓存中的数据刷到硬盘上
                    2.当缓冲区满了,自动就会刷到硬盘上

                    3.正常关闭文件:
                        1>.fclose
                        2>.return(main函数)
                        3>.exit(main函数)



            注意,linux系统函数,是没有提供I/O缓冲区的。
            这是与c库函数的不同点之一。



29.虚拟地址空间

            32位系统和64位系统
            为每一个进程分配0~2^32 和0~2^64
            的虚拟地址空间
            也就是4G和


            4G中0~3G是用户空间,后面1G是linux kernel

            linux kernel 内核区 部分还有PCB进程控制块  

            指向文件描述符表,其实是一个数组0~1023

            整形数组,宏定义。



            最前面,0 标准输入
                    1 标准输出
                    2 标准错误
                    默认是打开状态。


                    后面的序号,每打开一个新文件,
                    则占用一个文件描述符,而且使用的
                    是空闲的最小的一个文件描述符。



            内核区可以做什么呢?
                可以做  内存管理,
                        进程管理(PCB就属于这一部分),
                        设备驱动管理,
                        VFS虚拟文件系统。




            可执行文件是elf格式。

            命令: file sum

            #define NULL (void*)0


            这条语句指向哪呢,就是从0开始的0~4k
            地址,受保护的地址。

            ELF:
                .bss(未初始化全局变量)
                .data(已初始化全局变量)
                text(代码段,二进制机器指令)


            栈空间(小):分配地址,高地址-》低地址

            堆空间(大):分配地址,低地址-》高地址



            那么说回来,我们为什么要用什么鬼
            虚拟空间

            cpu为什么要使用虚拟地址空间与物理地址空间映射,
            解决了什么问题?

            1.方便编译器和操作系统安排程序的地址分布。
                程序可以使用一系列相邻的虚拟地址来
                访问物理内存中不相邻的大内存缓冲区。

            2.方便进程之间隔离
                不同进程使用的虚拟地址彼此隔离,
                一个进程中的代码无法更改正在由
                另一进程使用的物理内存。

            3.方便OS使用你那可怜的内存
                程序可以使用一系列的虚拟地址来访问大于
                可用物理内存的内存缓冲区。
                当物理内存供应量变小时,
                内存管理器会将物理内存页(通常大小为4KB)
                保存到磁盘文件。
                数据或代码页会根据需要在物理内存与磁盘之间移动。






30.C库函数和系统函数的关系:

            c标准函数
            printf函数->标准输出stdout:FILE*

            调用write函数将文件描述符传送

            到linux系统API
                应用层: write(fd,"helo",5)

                    操作0~3G
                    通过用户空间->内核空间 的转换

                系统调用:

                    sys_write()
                    操作3G~4G
                    调用设备驱动

                内核层设备驱动函数:

                    通过设备驱动操作硬件

                硬件层:

                    将hello输出到显示器。











31.linux 系统常用I/O函数:

            1.open()函数


            光标移动到对应的函数字母上
            按下 alt+K 
            跳转到对应的函数帮助文档。

                打开方式:
                    O_RDONLY
                    O_WRONLY
                    O_RDWR

                可选项:
                    O_CREAT
                        文件权限:
                            本地有一个掩码
                                用 umask 
                                可以查看。
                                掩码 可以修改。
                                也是用umask
                                如: umask 022

                            所以,文件实际的权限
                                给定的权限
                                本地掩码(取反)
                                按位与操作

                                得出实际的操作。


                    O_TRUNC
                    O_EXCL
                    O_APPEND




                2.用open函数判断一个文件是否已经存在。

                    fd=open("myhello",O_RDWR | O_CREAT | O_EXCL,0777);


                3.将文件截断为0:


                    fd=open("myhello",O_RDWR | O_TRUNC);


                需要注意的地方就是:
                对函数的返回值进行判断
                ,最后输出。




            2.read()函数:
                返回值:
                    1. -1 读文件失败
                    2. 0 文件读完了
                    3. >0 读取的字节数


            3.write()函数:
                返回值:


            4.lseek()函数:

                    1.获取文件大小;
                    2.移动文件指针;
                    3.实现文件拓展。只能往后拓展,不能往前拓展。
                        50m拓展为100m。

                        int ret = lseek(fd,2000,SEEK_END);
                        向后拓展2000.必须在最后做一次写的操作。
                        不管写什么,随便写点东西。

                        write(fd,"a",1);







32.linux文件操作相关函数:

            1.stat函数:
                获取文件的属性信息。

                使用举例:
                    stat english.txt


                通过stat函数实现ls -l功能。


                对参数的分类:传入参数,传出参数。对应于读参数,写参数。


            stat函数,穿透(追踪)函数--软链接,比如vi

            lstat函数,不穿透(不追踪)函数。比如一些命令ls -l。rm


            2.access函数

            用man 2 access 进行函数查询

            3.strtol函数

            4.chown函数


            5.man 5 passwd  密码文件

            6.truncate函数


            7.link函数
                创建一个硬链接。

            8.symlink函数

                创建一个软链接。

            9.readlink函数
                读一个软链接。


            10.unlink函数

                1.如果是符号链接,删除符号链接;
                2.如果是硬链接,硬链接数减一,当减为0时,
                    释放数据块和inode;
                3.如果文件硬链接数为0,但有进程已打开该文件,
                    并持有文件描述符,则等进程关闭该文件时,kernel材真正
                    去删除该文件。