git config --global user.name "Your Name"
git config --global user.email "[email protected]"
1.新建目录,
mkdir git
cd git
2.通过git init初始化
git init
1.添加文件
git add readme.txt
2.添加到仓库
git commit -m "message"
git 可以分别add文件,然后用 commit一次性提交
D.时刻查看文件的改动
git status
git diff readme.txt
yubo@debian:~/git$ git diff readme.txt
diff --git a/readme.txt b/readme.txt
index f7249b8..aa5a885 100644
--- a/readme.txt
+++ b/readme.txt
@@ -1,2 +1,3 @@
Git is a version control system
Git is free software
+yubo
+yubo 就是新增的内容
删除文件的命令是:
git rm xx
git commit -a
git push xx
git reset --hard commit_id
git log
假设我再一次修改了readme.txt文件,`git status ->git add file ->git log`
yubo@debian:~/git$ git log
commit c581ae4fb9e9aa16bbe5927b454260f4dba2644e
Author: yubo <[email protected]>
Date: Fri Sep 19 10:12:17 2014 +0800
add distribute
commit 1e2113c000c662da0e8d8f13ec3a60252579a4f6
Author: yubo <[email protected]>
Date: Fri Sep 19 08:54:11 2014 +0800
wrote a readme.txt
注意,git log只会显示真正提交的文件,也就是git commit 才可以, 现在的git log 还没有第三次修改的文件,
git commit -m "third time distribute"
__git log__
yubo@debian:~/git$ git log
commit da09fadf5aa85f31682e16acdfca5d3e09f897f7
Author: yubo <[email protected]>
Date: Fri Sep 19 10:25:59 2014 +0800
third time distribute
commit c581ae4fb9e9aa16bbe5927b454260f4dba2644e
Author: yubo <[email protected]>
Date: Fri Sep 19 10:12:17 2014 +0800
add distribute
commit 1e2113c000c662da0e8d8f13ec3a60252579a4f6
Author: yubo <[email protected]>
Date: Fri Sep 19 08:54:11 2014 +0800
wrote a readme.txt
这样,你就可以使用git的时间线来调整git的版本了,从这里你也可以明白git的工作单元是 git commit后的文件。还有我们一开始没有讲,上面输出信息中 commit后面的一串乱码 是一个SHA1计算出来的非常大的数,这样保证版本号不会冲突。 B.接下来假设我们要使用第二版本的即 add distribute: 首先,git必须知道现在正在使用的是哪个版本,git用HEAD表示当前版本,上一个 版本就是HEAD^,上上版本就是HEAD^^,那么前10个版本怎么写?简单,就是HEAD~10 我们回退到上一版本
git reset --hard HEAD^
从以上内容中我们可以发现这个commit id是很重要的,我们不关掉 电脑的话查找commit id还是挺容易,但如果关掉PC的话,我们还是 有办法找到commit id的:
git reflog
所谓的工作区,也就是我们用ls命令打开看到的文件,我们创建一个文件后, 这个文件显式的位于这个目录下,经过add以后,这个文件被放在stage区域中或者说暂存区, 经过commit后,这些文件才被放在某一个分支下(如master),同时这里还会有一个 HEAD的指针指向文件,我们上面使用的git reset –hard xx就是将这里的指针 移动到某个历史文件上。这些东西全部由.git的目录在控制,所以,没事千万别乱动 那个.git目录。当你把所有修改后的文件commit后,工作区这时也就是干净的了。
git的本质是管理修改,而非文件,这一点请务必弄明白。
如果我们修改的文件有不合适的地方,或者撤销这个修改,这该怎么办?Git还是有办法解决这个问题的,不知你有没有注意到上面那些屏幕输出的信息中,就包含了这个问题的解决方案,那就是运用 git checkout – readme.txt ,假设我把readme.txt文件最后一行去掉
yubo@debian:~/git$ git checkout -- readme.txt
yubo@debian:~/git$ cat readme.txt
Git is a version control system
Git is free software
yubo
hahah
I like git
You like git too
这就是在没有 commit命令我们用 checkout 的效果.假设我们git add到暂存区后怎么办?一种方案就是用我们刚刚使用的 git reset HEAD file命令回到原先的版本。
yubo@debian:~/git$ git status
yubo@debian:~/git$ git add readme.txt
yubo@debian:~/git$ git status
yubo@debian:~/git$ git reset HEAD readme.txt
重置后撤出暂存区的变更:
M git-2
M readme.txt
git reset 命令既可以实现回退版本,也可以把暂存区的修改撤销掉,当我们用HEAD时,表示最新的版本。
yubo@debian:~/git$ git status
# 修改: readme.txt
修改尚未加入提交(使用 "git add" 和/或 "git commit -a")
我们继续使用丢弃工作区的命令,
yubo@debian:~/git$ git checkout -- readme.txt
修改尚未加入提交(使用 "git add" 和/或 "git commit -a")
git rm file
如果误删了,接着使用 checkout 命令还原。不过,记住,这样只能 恢复到最新版本的文件,你删除文件的最后一次修改是无法恢复的,
远程搭建服务器:
先添加一个具有sudo权限的用户 安装git
创建一个git用户,用来运行git服务 sudo adduser git
创建证书登录 收集所有需要登录的用户公钥,就是他们的id_rsa.rub文件,把所有公钥导入 /home/git/.ssh/authorized_keys文件中,一行一个
#Linux Kernel Development 读书笔记
(8/10/14)
==========================day01===================
1.Introduction to linux:
1.kernel,device drivers,boot loader,command shell,filetype system utilities
2.linux can dynammic loading of kernel modules or unloaded;symmetrical multiprocessor(SMP?);all process are the same
3.Andrew Morton LKML
4.practical
2.Getting started:
1./usr/src/linux !!!不能动
2.using patches
3.Configuring the kernel
4.GNU c:inlines;Assembly:empty if();No memory Protection==>oops;No Floating Point
3.Process Management
1.The living result of running program code
2.Thread within the process,内核调度包括thread,not process.Modern operating systems provide two virtuazation:a virtualized processor and virtual memory
3.fork() begins process’s life,exit() end it’s life,exec() begins a new address space and loads a new program into it
4.task list consist of circular doubly linked list,
Each element in the task list is a process descriptor of the type struct task_struct
5.Allocating the Process Description:thread_info structure is defined on x86 in <asm/thread_info.h>,I want to know what he is taking about,
Process identification value or PID
6. maximum value is recorded in /proc/sys/kernel/pid_max.via the “current” macro
7.Process State(5个)==>set_task_state(task,state)/set task task
to state state
/
8.Process Context
9.The Process Family tree,the big father is PID is one(init in last step of the boot process),总的来说,就是在引导boot程序的最后一步时由init呼叫其他系统程序,完成了启动后即开始转换为big father,“struct task_struct *my_parent = current->parent”
10.Process Creation,fork()将父进程的所有资源复制给他的子进程,在这里,这两者之间用了一种锲约Copy-on-write(这是一种延迟(delay)),等时机差不多了再复制资源,所以,像连环套似的,下一个宝藏就是–copy-on-write,BTW,学习计算机,我自己最大的感受是当你看到一种新理论或者新名词时,最好不要去想这东东我能用着吗,我要掌握那得花多少时间啊,想都不要想,当然,如果你是按主题搜索资料时,还是要注意大方向的。
11.Forking:The fork() via the clone() system call,do_fork()
12.The Linux Implementation of Threads:They can also share open files and other resources,Thread enable concurrent programming and on the multiple processor systems ,true paralleism.But Linux kernel ,there is no concept of a thread,Linux implements all threads as standard processes.just happen to share resources ,such as an address space,with other process.linux没有线程的概念,这一点与windows与Solaris显然不同,也是存放在task_struct中在<linux/sched.h>有着clone flags的定义。
13.Kernel threads-standard processes,do not have an address space (mm pointer ,which points at their address space ,is NULL) ,内核线程有很多,如 top,ps -ef啦,第一次读到源代码,宏的使用比较多,还有各种各样的强制转换
============================chapter04==========
Process Scheduling
1. Multitasking,四个问题, suspending a running process is called preemption(?),timeslice ,yielding
2.linux’s Proces Scheduler is simple,But 2.5 kernel later call O(1) scheduler,get to constant-time,and 2.6.23,the completely fair scheduler or CFS.
3.主要讲了两类Bound,I/O,process
4.process priority,linux kernel have two separate priority ranges(-20 to +19 with a default of 0),shell ps -el
5.Real-time
6.关于linux的时间调度,有几个值得关注的地方:
1. Time Accounting
2. The scheduler entity struct,这个结构体定义在<linux/sched.h>中,并且这个结构实体嵌入在进程描述表中。
3.The virtual Runtime 记录了进程的实际运行时间,是上面结构体的一个成员。nanoseconds(十亿分之一,毫微秒)。
4.进程选择(process selection),这里涉及红黑二叉树,自己还是一无所知,补上啊.红黑树的定义在/linux/sched.h中,这个数据结构在内核中异常重要,在不同场景中都有它的应用,请你自己一定要掌握下来。
5.Picking the Next Task: 在红黑树的基础上,选择下一个任务就简单多了,选择rb_node的leftmost node就是了,而这个函数就是__pick_next_entity(),在 kernel/sched_fair.c中。
6. Adding process to the Tree : first created via fork(),then enqueue_entity(),将进程加入红黑树。
7. Removing Process from tree
8. The Scheduler Entry Point
9. Sleeping and Walking Up
———————-chapter 5 system call———–
———————-chapter 7 interrupt ————
–Work Queues–
struct workqueue_struct { struct list_head pwqs; /* WR: all pwqs of this wq / struct list_head list; / PL: list of all workqueues */
struct mutex mutex; /* protects this wq */
int work_color; /* WQ: current work color */
int flush_color; /* WQ: current flush color */
atomic_t nr_pwqs_to_flush; /* flush in progress */
struct wq_flusher *first_flusher; /* WQ: first flusher */
struct list_head flusher_queue; /* WQ: flush waiters */
struct list_head flusher_overflow; /* WQ: flush overflow list */
struct list_head maydays; /* MD: pwqs requesting rescue */
struct worker *rescuer; /* I: rescue worker */
int nr_drainers; /* WQ: drain in progress */
int saved_max_active; /* WQ: saved pwq max_acti
}
这是在高版本的内核中实现的,与LKD上的代码不是很一样 3. The relationship between work,work queues,and the worker threads 4. Here can you use bottom half: softirqs,tasklets,work queues; 这三方面当然有侧重点了,不同的应用对应不同的功能 5. 以上就是defer work(延迟工作); -----------------------Kernel Synchronization--------- 1. Code paths that access and manipulate shared data are called critical regions.(在这里的临界区和操作系统的临界区不知道是不是一回事) 2. Race Conditions:
这里指的是两个线程共同分享一个临界区(Critial Region),为了预防这种情况的发生就叫做 Synchronization 3. 作者举的两个例子很熟悉,一个是ATM取款,另一个是数据库中的读脏数据的例子。原子操作是避免这类错误的根本。 4. 在Linux中,A value of zero means unlocked.On the popular x86 architecture,locks are implemented using such a similar instruction called compare and exchange. 5. The kernel has similar causes of concurrency:
1.Interrupts
2.Softirqs and tasklets
3.Kernel preemption
4.Sleeping and synchronization with user-space
5.Symmetrical multiprocessing 6. Knowing What to protect
It's to identify what data does not need protection and work from there. 7. Most global kernel data structures need locking! 8. deadlocking
Whenever you write kernel code,whether it is a new system call or a rewritten driver,protecting data from concurrent access needs to be a primary concern. ----------------Kernel synchronization methods---------- 1. Atomic Interger Operations
atomic_t type is define in <linux/types.h>,finally,use of it can hide any architecture-specific differences
typedef struct {
volatile int counter;
} atomic_t;
好几种关于atomic operations,书本现在读不进去,苦恼中
<asm/atomic.h>
Here, for example:
static inline void atomic_add( int i,atomic_t *t)
{
asm volatile(LOCK_PREFIX "addl %1,%0"
: "+m" (v->counter)
: "ir" (i));
}
/*
*解释这是GCC的扩展应用,具体用法是这样的 1. asm [volatile] (AssemblyTemplate : [OutputOperands] [ :[ InputOperands][:[Clobbers] ] ] )
在ISO C中可以使用 _asm_ 替代asm,_volatile_替代volatile.
*
*/
----volatile意思是不要对其进行优化,这里不优化的话,就会被汇编成直接访问内存地址,而不是操作寄存器
这里会被汇编成一条语句,%0 代表output,%1代表i,output和input的"m"和"ir" 是这种扩展嵌入汇编的constraint,m代表这需要访问内存地址来取出数值,i代表这个立即数,r代表可以放到任何的寄存器中 2. 64-bit Atomic Operations
With the rising prevalence[普及] of 64-bit architecture ,32位机器的原子操作会逐渐移植到64位,但是自己在开发的时候一定注意机器的字长。 3. Atomic Bitwise Operations 4. Spin Locks
spin locks can be used in interrupt handlers,be care when you attmpte to obtain spin locks you have alread hold,It's possible can't obtain spin lock never! 5. spin_lock_irqsave() saves the current state of interrupts,disables them locally. There are a rule: Big Fat Rule. 6. Semaphores in linux are sleeping locks. 7. BKL: The Big Kernel Lock 8. Sequential Locks.It works by maintaininng a sequence.
After i cast much time,i am on the way to the Linux Kernel. But how i start to code?
P234 11-14 ##two handware devices to help with time keeping ###the real-time clock The real-time clock(RTC) continuous to keep track of time even the system is off,on PC architecture the RTC and CMOS are integrated. On boot,the Kernel reads the RTC and uses it to initialize the wall time,which is stored in the xtime__variable. ###The timer interrupt is broken into two pieces,an architecture-dependent and architecture-independent,but both at least perform the following working. 1.obtain the __xtime_lock__lock,which protects access to __jiffies_64__and wall time value–xtime. 2.reset the system timers as required 3.Periodically save the updated wall time to the RTC 4.Call the architecture-independent the timer routin__tick_periodic(),后面这个函数是个重点。
====================================================== overhaul:检修;改造:rectified:矫正 to a fault:fellowship(团契)::latency::at-odds:: http://v.163.com/movie/2014/9/5/8/MA44SCUPU_MA47GQ658.html scenario::coexist::protocols::dabbled::coupons::bot:: ============================================ debian 分区工具 apt-get install parted
#疑惑
可是说上大学以来读了不少的书,可是有多少留下印象了呢,借了还,还了借,如此循环。只不过今晚同学把CSAP借出来了,使我很吃惊,因为我找这本书好久了,一直没有找到,现在想想,这本书的电子版还在文件夹下放着呢,我的时间都去哪儿了? #计划 也许世界上最不靠谱的就是计划了,更何况是我的计划,但是今晚把自己的读书计划放在这,也没有什么害处,还能时不时更新读书笔记,多好的事情!(时时更新) ##Linux Kernel D
之前重新编译了好多次,可惜没有一次成功的,说实话,借助Debian强大的dpkg软件包管理,使得重新编译内核仅仅像安装软件一样简单,我都觉得这不是正宗的编译内核,好了,废话不多说,马上进入主题。
我没有使用最新的内核源代码,用的 3.2.64,我们可以在http://www.lkml.org下载,注意这里我们下载的是.xz文件,需要解压两次。至于源代码放在哪里,完全取决于你自己,你想放在哪里就放在哪里,我直接放在在用户主目录都可以啊。
xz -d linux-xx
(xx就是你下载的内核源代码的版本),这时生成.tar文件,然后
tar -xvf linux-xx
sudo apt-get install kernel-package libncurses5-dev fakeroot build-essential bc
利用git得到linus的最新 kernel,然后执行 make clean
,接下来执行
make menuconfig
如果你想单独编译某个模块,可以单独地编译那个模块(不建立镜像)
make drivers/usb/serial
下面可以建立镜像
make M=drivers/usb/serial
如果你想把内核镜像编译在别处,那么则可以使用
make O=~/linux-kernel-image-dir
看了这么多关于内核的东西,这两天终于上手实现了基于内核的编程——模块编程。 这里,简单的记录一下,因为还是有些东西需要牢记的。 先说点题外话,看到资料上说模块机制、设备机制、驱动机制是在linux上很重要的三种机制之一,所以,看起来,这真是万里长征的第一步。
#include<linux/init.h>
#include<linux/module.h>
#include<linux/kernel.h>
//上面的三个头文件必须有
MODULE_LICENSE("GPL");//模块许可声明
/*下面的__init 是一个宏,在include/linux/init.h里面*/
static int __init hello_init(void)
{
printk("Hello,world\n");
return 0;
}
static void __exit hello_exit(void)
{
printk("GoodBye\n");
}
/*初始化*/
module_init(hello_init);
/*退出时使用*/
module_exit(hello_exit);
简单解释一下,一个模块源程序的
1.头文件(必有)
2.模块参数(可选)
3.模块功能函数(optional)
4.模块加载函数(必有)
5.模块卸载函数(必有)
6.模块许可声明(必有)。
ifeq ($(KERNELRELEASE),)
VERSION_NUM :=$(shell uname -r)
CURRENT_PATH :=$(shell pwd)
KERNEL_DIR :=/usr/src/linux-headers-$(VERSION_NUM)
modules:
$(MAKE) -C $(KERNEL_DIR) M=$(PWD) modules
modules_installs:
$(MAKE) -C $(KERNEL_DIR) M=$(PWD) modules_installs
clean:
rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions *.order *.symvers
else
obj-m := module.o
endif
关于Makefile文件的知识不是这篇文章的内容,但我们会努力讲解的简单明了一些。其中使用了shell中的选择判断语句,先取得当前系统的版本号,模块源文件所在的目录、内核文件的目录、然后就是目标依赖关系,当然这部分我自己也是不很明白,还需要彻底了解一下相关知识。看上去先产生模块,然后安装modules,这些都是make命令执行后运行的东西。如果我们执行 make clean 紧接着就是清除所在目录产生的中间文件文件,当然,你可以添加自己的规则。
上面的 Makefile是针对于你的发行版的,找到你的镜像(kernel)头文件包,下面是 linux kernel tree编译内核模块的方法
obj-m += module.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
使用这个 Makefile 就可以在自己编译的内核中编译自己的模块,记住一点,你正在运行的内核与 linux kernel tree必须一致,不然会有错误报出。
好,我们将所有的准备工作做好后,执行一下,(sudo 模式)
make
我们会看到如下信息:
紧接着执行
insmod module.ko
,我们打开另一个终端,执行命令
tail -f /var/log/message
我们回到原来的窗口再执行
rmmod module.ko
这两条命令执行后在另一个窗口我们会看到如下信息:
回到原来的窗口,我们执行 make clean,就只剩下了原来的文件。
Linux为用户提供了modutils工具,用来操作模块,包括以下命令
这个命令是加载模块,使用 insmod module.ko可以加载module.ko模块,执行该命令后如果终端没有消息,则可以使用命令 demsg | tail 命令查看文件的最后几行. |
rmmod module.ko就是将module.ko模块卸载。
比较高级的加载和卸载模块的命令,可以解决模块之间的依赖性。
用于查询模块的相关信息,如作者、版权等。
#问题阐述 最近安装了很多的软件,总是为了折腾linux而为的,今天晚上不小心把Bochs安装完毕,在此发文纪念一下了。
由于安装这个这个bochs中间因为网站的问题而搁置了好几天,但在linux系统下安装bochs总不能少了那几个软件包的支持,具体是哪几个我忘了。 #步骤
1.首先到bochs.sourceforge.net下载bochs源代码包并解压缩。
2.然后要安装五个软件,否则make,make install时会失败。
apt-get nstall build-essential xorg-dev bison libgtk2.0-dev libtool libx11-dev xserver-xorg-dev
3.进入所在目录,开始配置
./configure –enable-debugger –enable-disasm
两个enable分别表示启用bochs调试和反汇编。
4.make
5.make install
这只是把软件安装上了,最重要的一步还没做:配置bochs的文件。 由于我把bochs文件解压到用户目录下,所以该配置文件.bochsrc就可以放在用户目录下
##tips 网上有教程说配置liunx0.11内核,关键是我不知道这有什么作用,下面是linux0.11网址 linux 0.11
6.配置bochs启动文件
#how much memory the emulated will have
megs: 32
#filename of ROM images
romimage: file=/home/yubo/bochs/bios/BIOS-bochs-latest
vgaromimage: file=/home/yubo/bochs/bios/VGABIOS-lgpl-latest
#vga: extension=vbe
#what disk image will be used
floppya: 1_44=/home/yubo/a.img,status=inserted #注意路径一定要写全,我这里把镜像文件放在了用户目录下的中,下同
#floppyb: 1_44=/home/yubo/bochs/linux0.11/rootimage-0.11-20040305,status=inserted #注意路径一定要写全
#choose the boot disk
boot: floppy
log: bochsout.txt
#disable mouse
mouse: enabled=0
看到没,我们对Bochs的控制全在这里,包括映像文件的路径和启动顺序,至于a.img是在怎么来的,请看下面的东东,我们将配置文件写好以后,使用命令
bochs
会出来选项,直接回车(就是选择6),然后弹出一个窗口,在原来窗口的提示内键入
c
这时你再看模拟器窗口,啊,整个世界开朗了。 #Bochs的使用 其实在上面的安装过程中,我可能遗漏了很多组建,默认安装Bochs及其组件可以使用以下命令:
sudo apt-get install vgabios bochs bochs-x bximage
当然,首先推荐使用源码安装这样可以设置一些自己想要的功能,比如调试。
“计算机”安装好了,我们接下来应该怎么办呢?对了,安装硬盘或者软盘,你总得让计算机启动吧,就是使用__bximage__命令。
bximage:
出现以下界面,
yubo@debian:~$ bximage ======================================================================== bximage Disk Image Creation / Conversion / Resize and Commit Tool for Bochs $Id: bximage.cc 12364 2014-06-07 07:32:06Z vruppert $ ======================================================================== 1. Create new floppy or hard disk image 2. Convert hard disk image to other format (mode) 3. Resize hard disk image 4. Commit 'undoable' redolog to base image 5. Disk image info 0. Quit Please choose one [0] 1 Create image Do you want to create a floppy disk image or a hard disk image? Please type hd or fd. [hd] fd Choose the size of floppy disk image to create, in megabytes. Please type 160k, 180k, 320k, 360k, 720k, 1.2M, 1.44M, 1.68M, 1.72M, or 2.88M. [1.44M] What should be the name of the image? [a.img] Creating floppy image 'a.img' with 2880 sectors The following line should appear in your bochsrc: floppya: image="a.img", status=inserted
这时在当前目录下产生了一个 a.img,这就是我们需要的软盘映像(自己想把img文件的格式学习一下,结果网上的资料不是很多),书上说映像文件是按字节复制,记住,a .img只是一个软盘,没有任何东西,我们接下来要把编译的二进制文件(引导扇区)写进软盘里
yubo@debian:~$ dd if=boot.bin of=a.img bs=512 count=1 conv=notrunc 记录了1+0 的读入 记录了1+0 的写出 512字节(512 B)已复制,9.3823e-05 秒,5.5 MB/秒
稍微解释一下这个命令,if是input file的缩写,of是out file的缩写,也就是目标文件,bs是文件的大小,count不是很清楚,conv=notrune是不要截断. 注意路径问题就行
nasm boot.asm -o boot.bin
org 07c00h ;load first instructor notify compile
mov ax,cs
mov ds,ax
mov es,ax
call DispStr ;call char functions
jmp $; loop
DispStr:
mov ax,BootMessage
mov bp,ax
mov cx,16
mov ax,01301h
mov bx,000ch
mov dl,0
int 10h
ret
BootMessage: db "hello,OS world!"
times 510-($-$$) db 0
dw 0xaa55
简单介绍下这个文件的意思,引导扇区,是从0面0磁道1扇区到0xAA55,之间应包含少于512字节的执行码,一旦BIOS发现了引导扇区,就会将这512字节的内容装载到内存地址0000:7c00处,然后跳转到0000:7c00处将控制权交给这段引导代码。