主页

git起步

2021-01-28
git

  • git:每一次的clone操作,实际上都是对一次代码仓库的完整备份。
  • git中文件的三种状态:已修改(modified)和已暂存(staged),已提交(committed):
    • 已修改tag1表示已修改了某个文件,但还没有提交保存(git add之前);
    • 已暂存表示把已修改的文件放在下次提交的清单中(git add 之后);
    • 已提交表示该文件已经被安全保存在本地数据库中(git commit之后);
  • 每个项目都有一个git目录(.git),git工作流程如下:
    1. 在工作目录(.git的兄弟目录)中修改某些文件;
    2. 对修改后的文件保存到暂存区域;
    3. 提交跟新,将暂存区域的文件快照转储到git目录中。
    4. 提交到远程仓库。

开始 #

  1. 安装git,配置个人用户名称和电子邮件地址。 git config --global user.name "xiaoxiang" git config --global user.email "xiaoxiang@xxxx.com"
  2. 可以使用git config --list查看已有的配置信息。
  3. 从现有的git仓库克隆git clone [远程仓库]
  4. 工作目录下的文件分为两种状态:已跟踪和未跟踪:
    • 已跟踪是本地仓库中有的文件,初次克隆某个仓库时,工作目录的所有文件都是已跟踪的文件。
    • 未跟踪是新创建的文件,即对该文件从来没有执行git add命令。
    • 当编辑过某些文件后,git将这些文件标记为已修改,这就跟 tag1对于上了。
  5. 使用git add开始跟踪一个新文件,git add .暂存当前路径下的所有的已修改的文件。
    • 通过git status可以查看文件的状态。
    • 取消已暂存的状态git reset [--mixed] HEAD "文件名",该方式会清除暂存区的数据,保留工作目录的数据。
  6. 使用git commit -m "提交说明"来提交暂存区的数据到本地仓库
  7. 使用git push origin master 将修改提交到远程仓库。(使用ssh-keygen生成密钥,并将公钥放到git上去,以后提交就不用输账号和密码了)。
    • git push [remote-name] [branch-name],这是完整命令。

.gitignore #

  • 可以创建一个.gitignore文件,来指明哪些文件不需要被提交到仓库。

  • .gitignore文件的格式规范如下:

    • 所有空行或者以#开头的行都会被Git忽略。
    • 忽略指定的模式以外的文件或者目录,可以在模式前加上!
    • 匹配模式以/开头防止递归。
    • 匹配模式以/结尾防止递归。
    • *匹配零个或多个任意字符,[a-c]匹配任意一个列在方括号中的字符,?只匹配任何一个字符,**表示匹配任意中间目录。
#忽略所有的.a文件
*.a
#跟踪所有的lib.a,即使在前面忽略了.a文件
!lib.a
#只忽略当前目录下的TODO文件,而不忽略subdir/TODO文件
/TODO
#忽略任何目录下名为build的文件夹
build/
#忽略doc/notes.txt,但不忽略doc/server/arch.txt
doc/*.txt
#忽略doc/目录及其所有子目录下的.pdf文件
doc/**/*.pdf

git stash #

  • git stash push [-m "暂存的备注"] 暂存当前的更改,并将本地恢复到HEAD。-m是可选的,该参数会给此次暂存加个备注。
  • git stash list 列出当前所有的暂存,最新的是stash@{0}
  • git stash pop 应用stash@{0},并删除stash@{0}。
  • git stash drop stash@{0} 从stash列表中删除stash@{0}。
  • git stash apply stash@{0} 应用stash@{0},但不删除stash@{0}

  • 查看文件修改了什么地方,可以使用git diff指令。
  • 查看提交历史git log,后跟-2只会显示最近两次的跟新。
  • 切换到其他分支git checkout master
  • git tag可以给某一时间点的版本打标签。
  • git update-index --assume-unchanged 文件名:取消本地跟踪
  • git update-index --no-assume-unchanged 文件名:恢复本地跟踪
  • 协议:
    • ssh协议:唯一一个同时支持读写操作的网络协议,但无法实现对仓库的匿名访问。
    • git协议:该协议通常用来克隆,通常不能用来推送(因为没有授权机制,如果允许推送操作,每一个知道该URL的人都有推送权限),比http协议高效。
    • http/s协议:容易搭建,通常用来克隆。

git remote #

#列出指定的每一个远程服务器的简写
git remote
#显示远程仓库的简写与对应的URL
git remote -v
#查看某个远程仓库的更多信息,会列出远程仓库的URL和跟踪分支的信息。
git remote show origin
#添加一个远程仓库,并指定一个简写
git remote add origin https://xxx.xxx/xxx/xxx
#修改仓库的远程地址
git remote set-url origin 仓库地址
#远程仓库的重命名
git remote rename origin paul
#移除一个远程仓库
git remote remove paul
#git fetch只会将数据下载到本地仓库,并不会合并。需要手动合并
git fetch origin
#自动抓取远程分支并合并到本地分支
git pull

git branch #

  • 只有在本地修改或者产生了文件才会创建主分支master,这个时候才能创建新分支。
  • git branch查看所有的分支,*表示当前分支。
  • git checkout -b testing相当于git branch testing (创建一个分支)和 git checkout testing(切到该分支)
  • 删除分支git branch -d testing
  • 分支的合并:在当前分支下(如master),执行git merge testing,会创建新的commit对象,master也会指向他。该commit对象有两个父指针。
  • 分支的合并会用两个分支的末端以及他们的共同祖先进行一次的三方合并,当两个分支在同一个commit链上时,旧一点的那个分支发起合并,则将其直接指向了新一点的那个分支。
  • 有时候分支合并会失败,比如两个分支同时修改了相同的文件。这个时候git merge testing仍然做了合并,但是没有提交,可以使用git status查看,此时就需要手动合并了。
  • git branch --merged查看那些分支已被并入当前分支。git branch --no-merged查看尚未合并的分支。

参考链接: Pro Git

参考链接: Git - 记录每次更新到仓库 (git-scm.com)

参考链接:开源指北

文件

2021-01-27
linux

目录介绍 #

根目录 #

目录 介绍
/bin (binary)存放很多可执行的指令,该路径下的指令可以被root和一般账号所使用,比如cat,chmod,mv,bash等
/boot 存放开机会使用到的文件,如/boot/grub
/dev linux中任何外部设备都是以文件的形态存在于这个目录中
/etc 系统主要的配置文件几乎都在这个目录中,
/lib 存放开机时会用到的库,以及在/bin或/sbin下面命令会调用的函数库。(/lib64:用来存放于/lib不同格式的支持64位的二进制函数库)
/media 存放的是可移除的设备,如光盘、dvd等,能暂时挂载到这里
/mnt 可以用来暂时挂载某些额外的设备
/opt 如果自行安装(不使用apt或yum命令安装的)可以放到这里,但一般还是习惯放到/usr/local中
/run 规定开机后所产生的各项信息要放到该文件夹中
/sbin 设置系统环境的,包括了开机、修复、还原系统所需要的指令。某些服务器软件程序一般放到/usr/sbin中,而向本机自行安装的软件所产生的系统执行文件,则放置在/usr/local/sbin中。
/srv (service)是一些网络服务启动后,这些服务所需要取用的数据目录
/tmp 暂时放置文件的位置
/home 系统默认的使用者主文件夹。如bes用户的默认文件夹就是/home/bes
/root root的主文件夹
/lost+found 使用ext文件系统格式才会产生的目录,目的是当文件系统发生错误时,将一些遗失的片段放到这
/proc 这个目录下的数据都在内存中,所以本身不占磁盘空间。如/proc/cpuinfo等。
/sys 主要记录与核心与系统硬件信息较相关的信息。不占磁盘空间
/usr (unix software resource)与软件安装有关;
/var (variable)与系统运行过程有关。

/usr #

目录 介绍
/usr/bin 一般用户能使用的指令放到这。centos7已经将全部的用户指令放到这里,使用链接的方式将/bin链接于此。
/usr/lib 与/lib功能相同,/lib就是链接到此目录中的。
/usr/local 在本机自行安装自己下载的软件,建议安装到此目录。
/usr/sbin /sbin就是链接到此目录。
/usr/share 好多文档都在这里。如/usr/share/man(在线说明文件)
/usr/include c/c++等头文件和include文件的放置位置
/usr/src 源代码建议放到这里。
/usr/libexec 某些不被一般用户惯用的执行文件或脚本等都放在此目录。例如大部分x视窗下的操作指令很多都放在此目录下。
/usr/lib64 /lib64就是链接过来的

/var #

目录 介绍
/var/cache 应用程序运行过程产生的一些暂存盘
/var/lib 程序本身执行的过程中,需要使用到的数据文件放置的目录
/var/lock 某些设备或者是文件资源一次只能被一个应用程序所使用。
/var/log 登陆文件放置的目录
/var/run 某些应用程序启动后,会将他们的pid放置到该目录,这个目录链接到了/run

/proc #

目录 介绍
目前主机上的各个进程的PID都是以目录的形态存在/proc中,如PID为1的所有相关信息都写入在/proc/1/文件夹下。
/proc/cmdline 加载 kernel 时所下达的相关指令与参数!
/proc/cpuinfo 本机的cpu相关信息,包含频率、类型。
/proc/devices 这个文件记录了系统各个主要装置的主要装置代号
/proc/filesystems 目前系统已经加载的文件系统
/proc/meminfo 使用 free 列出的内存信息,在这里也能够查阅到!
/proc/loadavg top 以及 uptime 的三个平均数值就是记录在此!
/proc/modules 目前我们的 Linux 已经加载的驱动程序
/proc/mounts 系统已经挂载的数据,就是用 mount 这个指令呼叫出来的数据啦!
/proc/swaps 到底系统挂加载的内存在哪里?使用掉的 partition 就记录在此。
/proc/partitions 使用 fdisk -l 会出现目前所有的 partition ,在这个文件当中也有纪录。
/proc/version 核心的版本,就是用 uname -a 显示的内容
/proc/bus/* 一些总线的装置,还有 USB 的装置也记录在此

Linux文件信息 #

-rw-r--r-- 1 bes bes 2625 Jan 27 11:11 _config.yml

  • 第一栏表示文件类型和权限;
    • 第一个字符代表该文件的类型,-表示文件,d表示目录,l表示链接文件(link),b表示区块文件如硬盘,在/dev/sda(block),c表示字符设备文件,如鼠标键盘(character),s表示数据接口文件(sockets),p表示数据输送档(FIFO,pipe)。
    • 下来9个字符每三个为一组(r表示可读,w表示可写,x表示可执行,-表示无该权限):
      • 第一组表示文件拥有者可具备的权限;
      • 第二组表示加入此群组的账号的权限;
      • 第三组为非本人且没有加入本群组的其他账号的权限。
  • 第二栏表示有多少文件名链接到此节点(i-node);
  • 第三栏表示该文件所属的用户,第四栏表示所属群组;
  • 第五栏表示容量大小,第六栏表示最近的修改时间,第七栏为文件名。

tips #

  • 如果用户对一个目录只有只读权限,那么是无法进入此目录的,他必须持有执行权限。
  • 对目录有只读权限表示它可以查看该目录下的文件名数据(用ls+目录名)。
  • 对目录有写权限表示它可以对该目录下的文件或目录执行:①新建文件和目录;②删除文件和目录(不论该文件的权限是什么);③修改文件或目录名;④移动文件和目录。
  • root不受权限限制。
  • 文件的写权限指可以编辑文件,但不包含删除文件。
  • umask:查看和设置文件权限。如002,表示user和group拥有全部权限,others拥有r和x权限。
  • 特殊权限(有些文件或目录会出现rws或rwt的情况,这就是特殊权限。注意:当S或者T为大写的时候,表示无效,因为使用者没有该程序的执行权限)
    • SUID(s):只对二进制文件(可执行的程序)有效;执行者要对该程序具有x的权限;在执行该程序时,执行者将短暂获得该程序拥有者(比如root)的权限。
    • SGID(s):可以针对二进制文件或目录来设置。对二进制文件:执行者要对该程序具有x的权限,在执行该程序时,执行者将获得该程序所在群组的支持。对目录:代表使用者在这个目录下面新建的文件的文件群组都会与该目录的群组名称相同。
    • SBIT(t):只针对目录有效,当使用者对该目录有w和x权限,只有自己和root才能删掉自己创建的文件或目录。
    • 权限和数字存在对应,SUID为4,SGID为2,SBIT为1。

文件系统 #

传统磁盘中,一个分区就是一个文件系统,但现在并不准确。文件系统通常将权限和属性放在inode中,将实际数据放到data block中。另外,有一个superblock记录整个文件系统的整体信息。

  • superblock:记录此文件系统的整体信息,包括inode/block的总量、使用量、剩余量,以及文件系统的格式与相关信息等;
  • inode:记录文件的属性(rwx、群组、时间参数等),一个文件占用一个inode,同时记录此文件数据所在的block号码;
  • block:实际记录文件的内容,若文件太大时,会占用多个block。 每个inode和block都有编号,inode内有文件数据的block号码。
  • 索引文件系统:上面的数据存取方法就是。
  • FAT:没有inode存在,每个block号码都记录在前一个block中,像一条链子一样。

Ext2 #

EXT2设置多个区块群组,每个区块群组都有独立的inode/block/superblock系统。 每个区块群组有6个部分:

  1. data block(数据区块):存放文件内容。Ext2中支持的block大小有1k,2k及4k,在格式化的时候就固定了,每个block只能放一个文件的数据。
1kB 2kB 4kB
最大单一文件限制 16GB 256GB 2TB
最大文件系统容量 2TB 8TB 16TB
  1. inode table(inode 表格):记录的数据:存取模式(rwx);拥有者和群组;文件的大小;文件创建时间,修改时间;读取时间;定义文件特性的flag;该文件内容的指向。
    • inode数量和大小在格式化时就固定了。
    • 每个inode大小固定为128B(新的ext4和xfs可以设置到256B);
    • 每个文件只会占用一个inode;所以文件系统能创建的文件数量与inode的数量有关;
    • 系统读取文件时需要先找到inode,在分析权限后,才进行下一步;

常量池

2021-01-27
java

常量池 #

  • 常量池中主要存放两大类常量:字面量和符号引用。
  • 字面量比较接近Java语言层面的常量概念,如文本字符串、声明为final的常量值等。
  • 符号引用包括了下面三类常量:类和接口的全限定命名、字段的名称和描述符、方法的名称和描述符。
  • 在class文件中不会保存各个方法、字段的最终内存布局信息,当虚拟机运行时,需要从常量池中获得对应的符号引用,再在类创建时或运行时解析、翻译到具体的内存地址中。

DataOutputStream的writeChars

2021-01-27
java

  • DataOutputStream的writeChars不推荐使用!
  • writeChars是将String直接拆成了byte(即先获取String对应的char数组,再将一个char分割成两个byte)。如果在客户端使用了该方法写入一个字符串,再在服务端读取,因为DataInputStream并没有readChars方法,只能使用read方法读取一个byte数组。这就会导致一个问题,byte数组转化为String会有一个编码的问题,服务端可能会出现错误。
  • 正确的姿势是使用DataOutputStream的write方法写入一个byte数组,两端使用相同的编码。

java随笔

2021-01-27
java

异常 #

  • 所有的异常都继承自Throwable;
  • Throwable有两个子类:Error,Exception。
  • Error描述了java运行时系统的内部错误和资源耗尽错误;
  • Exception有有两个分支,一个分支派生于RuntimeException,另一个分支包含其他异常。
  • 由程序错误导致的异常属于RuntimeException,例如:数组下标越界,错误的类型转换,空指针异常; 其他异常包括IOException,SQLException等。

线程 #

  • 对于sun jdk来说,它的windows版和linux版都是使用一对一的线程模型实现的,一条java线程就映射到一条轻量级进程中,因为windows和linux系统提供的线程模型就是一对一的。

cas #

  • cas指令需要有3个操作数,
  • 分别是变量的内存地址(V),旧的预期值(A)和新值(B)。
  • 当cas指令执行时,当且仅当V符合旧预期值A时,处理器用新值B更新V的值,否则他就不执行更新。 (但是无论是否更新了V的值,都会返回V的旧值。)
  • 上述的操作是一个原子操作。

class文件 #

  • 将一个局部变量加载到操作数栈Tload
  • 将一个数值从操作数栈存储到局部变量表Tstore
  • 将一个常量加载到操作数栈:bipush\sipush\ldc\Tconst_

Buffer

2021-01-27
java

Buffer #

  • 使用Buffer读写数据一般遵循四个步骤:①写入数据到Buffer;②调用flip()方法;③从Buffer中读入数据;④调用clear()或者compact()方法。
  • 缓冲区的本质是一块可以写入数据,然后可以从中读取数据的内存。
  • Buffer的三个属性:1.capacity 2.position 3.limit
    • capacity 表示该内存块的大小
    • position 当你写入数据到Buffer中,position表示当前的位置。当将Buffer从写模式切换到读模式时,position会被置为0。
    • limit 写模式下,limit等于capacity。当将Buffer从写模式切换到读模式时,limit表示你最多能读入多少数据,所以此时limit会被设置为写模式下的position值。
  • flip()方法将Buffer从写模式切换到读模式。调用该方法会将position设置为0,将limit设置为position的之前的值。
  • rewind()将position设回0。
  • clear()将position设置为0,将limit设置为capacity,表示可以写入了。
  • compact()将所有未读的数据拷贝到Buffer的起始处,然后将position设置到最后一个未读元素正后面,limit设置为capacity,表示可以写入了。
  • mark()可以记录一个特定的position。之后可以调用reset()恢复到这个位置。

java内存模型

2020-11-24
java

  • 原子性:保证指令不会受到线程上下文切换的影响
  • 可见性:保证指令不会受到cpu缓存的影响
    • synchronized和volatile都可以保证可见性
  • 有序性:保证指令不会受到cpu指令并行优化的影响

volatile #

  • 它可以用来修饰成员变量和静态成员变量,避免线程从自己的工作缓存中查找变量的值,必须到主存中获取它的值,线程操作volatile变量都是直接操作主存。

join和park

2020-11-19
java

join源码分析 #

  • join()是等待一个线程运行结束
public class Thread implements Runnable {
    //底层是使用wait()实现
    public final synchronized void join(long millis) throws InterruptedException {
        long base = System.currentTimeMillis();//开始时间
        long now = 0;//已经等待的时间

        if (millis < 0) {
            throw new IllegalArgumentException("timeout value is negative");
        }

        if (millis == 0) {//参数为0时会一直等待线程结束
            while (isAlive()) {
                wait(0);
            }
        } else {
            while (isAlive()) {
                //防止虚假唤醒,因为wait会被notify和notifyAll唤醒
                //唤醒后需要等待的时间是millis减去已经等待的时间
                long delay = millis - now;
                if (delay <= 0) {
                    break;
                }
                wait(delay);
                now = System.currentTimeMillis() - base;
            }
        }
    }
    
    public final void join() throws InterruptedException {
        join(0);
    }
}

park #

  • LockSupport.park();//暂停当前线程
  • LockSupport.unpark(暂停线程对象);//恢复某个线程的运行
  • 对应的线程状态还是wait状态
  • unpark可以在park之前执行,仍然可以恢复线程的执行