• 问题 文件的物理结构是什么样的

    文件系统中, 文件的物理结构是什么样的呢? 文件系统中, 怎么定义的文件的存储呢? 先记下这个问题, 以后看.

    #include <fcntl.h>
    #include <unistd.h>
    #include <stdio.h>
    
    int main(){
        int f = open("blank",O_WRONLY);
        if (f<0){
            perror("open error");
        }
        printf("%d\n",f);
        write(f,"abcdefg",7);
        lseek(f,10000000,SEEK_CUR);
        write(f,"abcdefg\n",8);
        close(f);
    }
    

    写一个空洞文件.

    root@2d3967f5850a:/tmp/test# ll blank
    -rw-r--r-- 1 root root 10000015 May  6 03:56 blank
    root@2d3967f5850a:/tmp/test# du -sh blank
    104K    blank 
    

    文件在大概10M, 但实际占用的磁盘空间只有104K

    但读取文件时候, 是会读取10M字节的内容的, cat blank > blank2, 然后再du也可以佐证.

    那文件系统中, 文件的物理结构是什么样的呢? 文件系统中, 怎么定义的文件的存储呢? 先记下这个问题, 以后看.

  • 通过nc来远程跑命令

    公司服务器登陆用了OTP(one time password), 每次登陆服务器都要输入不同的token, 有些麻烦. 大家讨论有哪些办法可以绕过去. 我想到了nc.

    以下全部没有任何实际价值, 仅供娱乐!

    在服务器上面:

    tail -0f p | nc -k -l 8000 | bash >> p
    

    在自己机器上面:

    nc 172.17.0.3 8000
    

    甚至可以传文件!

    先在自己机器上通过nc在服务器运行

    nohup nc -l 8001 > /tmp/a &
    

    然后在自己机器:

    cat 1 | nc 172.17.0.3 8001
    
  • umask使用

    umask是shell里面内置的一个命令. 设置进程的文件模式创建屏蔽码, 这个屏蔽码会在open/mkdir/mkfifo/mknod等系统调用时使用, 用来关闭文件模式中对应位置的权限位.

    op1@5ef1a50fef8f:~$ umask
    0002
    op1@5ef1a50fef8f:~$ touch 1
    op1@5ef1a50fef8f:~$ ll
    total 24
    -rw-rw-r-- 1 op1  op1     0 May  2 02:10 1
    op1@5ef1a50fef8f:~$ umask 0077
    op1@5ef1a50fef8f:~$ umask
    0077
    op1@5ef1a50fef8f:~$ rm 1
    op1@5ef1a50fef8f:~$ touch 1
    op1@5ef1a50fef8f:~$ ll
    total 24
    -rw------- 1 op1  op1     0 May  2 02:11 1
    
  • git删除远端tag

    git push origin :tagname

    git push --delete origin tagname

  • 每次read时的buffer size如何影响性能2

    昨天的时候有个疑问, /proc/diskstats里面的第四列, 也就是reads completed是什么. 和iostat显示的tps对比之后, 确认了, read tps取的值和reads completed就是一个.

    那应该就是说, read(fd, 1024000)的时候, 未必是一次”I/O request to the device”. 具体系统怎么处理read的, 继续学习.

    下午更新:

    在高手的指点下, 想通了. 至少在读文件(而不是裸设备)的时候, read(fd, 1024000)不是一次IO请求. 下面具体说一下:

    如果文件系统的blocksize也是4096. readahead设置成16, 也就是16*512=8192字节, 2个block.

    我们假设文件是顺序的.

    我原来的想法

    因为文件在磁盘中顺序存放的, 所以read(fd, 1024000)的时候, 一次性取1024000字节, 可以极大的减少磁盘IO次数. 但和测试下来的结果不符合, 所以很困惑.

    现在的理解

    OS在执行read file的时候,可不知道文件在磁盘中是顺序存在的,它需要在分析文件当前的block之后才知道下一个block在磁盘的哪里.

    如果一次性读取1024000这么多字节, 非常有可能后面很多数据都浪费了. 所以每次IO操作时, OS还是按照readahead配置来读.

    read(fd, 1024000)的时候, 是250个block. 因为有readahead, 所以一次会读8192字节. 如果磁盘是顺序的, 那么就是需要1024000/8192=125次IO requests

  • 每次read时的buffer size如何影响性能

    磁盘IO是比较费时的操作. 操作系统在每次读取磁盘的时候, 会认为接下来的文件内容可能在接下来很快再次读取,所以会预先就先读到内存中.

    这样可以查看当前系统的read ahead的值, 单位是512 bytes.

    blockdev --getra /dev/sda1
    

    这样可以配置read ahead的值, 单位是512 bytes.

    blockdev --setra 1024 /dev/sda1
    

    简单的脚本测试一下:

    echo 3 > /proc/sys/vm/drop_caches
    
    read1=$(cat /proc/diskstats | grep sda1 | awk '{print $4}')
    dd if=test of=/dev/null ibs=$@
    read2=$(cat /proc/diskstats | grep sda1 | awk '{print $4}')
    echo $((read2-read1))
    

    运行结果:

    # blockdev --setra 256 /dev/sda1 
    # ./go.sh 4096
    4194
    #
    # blockdev --setra 128 /dev/sda1 
    # bash go.sh 4096
    8233
    

    关于/proc/diskstats的解释

    疑问1

    我是计算的 ‘reads completed’ 的差值.

    This is the total number of reads completed successfully.
    

    这个到底是指的什么?

    系统调用的次数? 看上面的测试结果应该不是.
    实际磁盘IO的次数? 也会有矛盾.

    疑问2

    如果readahead是16(512 bytes), 16*512=8192

    read(16384)的时候, 会有几次磁盘IO? 看reads completed的值, 8192和16384没有区别.

    非疑问

    st_blksize 是4096, 所以readahead一定要是8的位数.

  • docker内存限制不能用free来查看

    这样可以限制容器中所有进程使用的内存数量

    docker run -it -m 300M ubuntu:14.04 /bin/bash
    

    但它是用cgroup来实现的, 在窗口中用free看不出来.

  • TODO

  • 见见朋友 打打球

    就是想找点事情做, 所以约了周末找出晓军打羽毛球. 到了前一天又有些纠结,觉得路途遥远, 有些累. 不过一天下来, 觉得还是比宅在家里好多了. 出来见下太阳打个球出个汗扯个淡见一下很久很久不见的同学,生活才更意思一点.

    PS, 骨科医生说了, 最好的坐姿是离桌子近一些,背上有个靠的,身体后仰. 不过最好还是站着. 所以我以后尽量站着工作吧.

  • 栈帧中的一些概念 1

    前不久想了解一下python中协程的概念, 看了greenlet源码. 看到slp_switch的时候, 里面是汇编语言, 搜索之后好像是需要了解栈帧的原理.

    基础太差, 看了好多文章, 才明白了一点点.

    1. 一个栈帧是一个被调用函数的一段内存空间
    2. ebp指向栈帧的底部, esp指向顶部, 即当前指向的内存地址.
    3. 入栈操作: push eax; 等价于 esp=esp-4,eax->[esp]
    4. 出栈操作:pop eax; 等价于 [esp]->eax,esp=esp+4

    一些文章:

  • 49
  • 50