原文地址 c语言中,任何变量都有一个地址,这个地址是由0和1二进制代码组成的,在声明变量 时,例如int,系统就会临时开辟一个存储空间,空间的大小根据类型的不同 而不同,最直接的表现就是分配的字节数不同。这个地址是硬件访问的依据,我们在源 代码定义的变量只不过是为了方便我们自己而定义的。 例如,定义如下:
int a; float b; double c; long double d;
假设它们所占的字节分别是4、8、8、10,而且连续存储一段空间地址,起始地址是100,则我们可以得到如下分布的东东:
|_a_| 100 |___| |___| |___| 103 |_b_| 104 |___| |___| |___| |___| |___| |___| |___| 111 |_c_| 112 |___|
为了节约空间我们不画出c,当然上面的阿拉伯数字就是地址了,不过在实际的内存中 ,是一连串的0和1,但思想是差不多的。所有这些类型都是编译器告知的,由于前面我 们已经定义了int型,则编译器知道从a的开始地址往后取4个字节再把它解释成int型( 等等,这里的意思是虽然编译器知道这个变量是多少字节,但机器访问的时候并不知道 ?,就感觉矛盾,前面既然只取了4个字节,为何还要再来一次呢)。那么(float)a,就 是先按照int类型取出该值,再将该值按照int to float的规则转换成float类型,一句 话总结就是,强制类型转换就是先按照原先的类型取出该值,然后按照** to **的规 则进行强制转换,如果是(类型名)常数这种形式,则是将该常数to类型的方式强制转换。
还有,变量名与内存空间的关联关系不是由硬件指定的,而是由编译器为我们实现的。
指针也是一个变量,它自己占据一个四字节的地址空间(因为程序的寻址空间是2^32, 即4GB,所以指针的4字节大小完全够用),它的值是另一个东西的地址,这个东西可以 是普通变量、结构体、还可以是函数等,由于指针的大小是4字节,所以,我们可以将 指针强制转换成int类型或其他类型,同样,我们也可以将常数转换成int型再赋值给指 针。所有指针的空间的大小都是4字节它们只是声明的类型不同。
指针to指针的强制转换是将指针所指的内容的类型由原来的类型转换为后面的类型。
int a = 1;
int *p = &a;
float *p1 = (float *)p;
则p和p1的值都是&a,但是p是将&a地址中的值按照int型变量进行解释,而p1则是将& a地址中的值按照float型变量进行解释。
ANSI C规定,void指针可以复制给其他任意类型的指针,其他任意类型的指针也可以 复制给void指针,他们之间复制不需要强制类型转换。当然任何地址也可以复制给void型指针。
自己原来在指针这块这么差啊,受不鸟自己了。
姑且这么理解,自己在网上看到一个比较的例子:
假如我们想让指针p指向浮点数f,那么就是p = &f吗,错,因为两边的类型不同,不能 直接赋值,需要强制转换。
p = (int *)&f;
如果有一个指针p,我们需要把它的类型和它所指向的类型改为TYPE *和TYPE,那么语法格式就是(TYPE *)p.
那么我们可不可以把一个整数当作指针的值直接赋给指针呢?就像下面的语句:
pm指向一个整型,cp指向整型的第一个字节。
这一部分的缺陷继续去阅读经典的书籍去填补
一个结构体定义type,这个结构体中某个成员变量的名字member以及它的地址ptr
包含此成员变量的结构体的地址
0 +------------+ <----我们要求的是这个地址 |a (4 bytes) | 4 +------------+ <----我们知道这个地址 |b (4 bytes) | 8 +------------+ |c (8 bytes) | 16 +------------+
通过以上分析我们不难得出,我们只需要把当前知道的成员变量的地址ptr,减去它在结构体当中的相对偏移量4就得到了结构体的地址(ptr-4)。在linux内核中,有一个很好的宏叫做container_of,
#define offset(TYPE,MEMBER)((size_t) & ((TYPE *)0)->member)
问题是,你能清楚的讲解上面语句的含义吗?我用了一天的时间去恶补基础,结果发现自己太菜了。
1.((TYPE *)0) 将零强制转换为TYPE类型的指针;
2.((TYPE *)0)->MEMBER 访问结构中的数据成员;
3.&(((TYPE *)0)->MEMBER) 取出数据成员的地址,即想对于0的偏移量,求的就是它。
4.(size_t)(&((TYPE *)0)->MEMBER) 结果强制转换,size_t应该最终为 unsigned int 类型。
结果是 8.
原本是想看Linux Kernel内核的,结果… 这篇文章纯属自己回忆瞎写,请不要当真。
struct tag { member-list } variable-list;
上面的粗体至少有部分;不知道c语言的发明者为什么会添了个标签,按照书上的解释,标签(tag)可以为成员列表提供一个名字,这样它就可以在后续的声明中使用,而且多个声明共同使用一个成员列表,并且创建同一种类型的数据结构。
这个声明创建了一个名叫x的变量,它包含三个成员:一个整数、一个字符和一个浮点。
这个声明创建了y和z,y是一个数组,它包含了20个结构,z是一个指针,它指向这个类型的结构。上面两个声明会被当作两种截然不同的类型。 ##标签的使用
我们以后想快速创建含有类似结构的结构体变量时,可以这样使用: struct SIMPLE x;
struct SIMPLE y[20],*z;
并且它们具有相同的类型。
使用结构体时,我们有一个东西不得不说:typedef;请看下例:
区别在于现在的Simple是一个类型名而不是标签了,我们可以这样使用:
Simple x;
Simple y[20],*z;
同上面使用标签是一样的。
关于字节对齐,根据机器类型来讲,有两类:一是内存上的,二是栈上的。为什么使用 对齐,主要从存取效率上考虑的,以某个整数的倍数为起点(也就是边界对齐)取一次数 据用一个?周期,但是如果不对齐的话则需要两次。continue….
最近想写linux设备驱动,发现不同参考书上的Makefile文件风格不一致,不一致是小事,我自己对这方面知识的欠缺总感觉穿着很重的鞋子走路。当然,网上的资料也是良莠不齐,自己看内核代码Document/kbuild中的文件算是做一下读书笔记,有错误的话还请谅解。
“kbuild” is build system used by the linux kernel.Modules must use kbuild to stay compatible with GCC. Modules programming is consist of in-tree and out-of-tree
$make -C
M=$PWD $make -C /lib/modules/\`uname -r\`/build M=$PWD
target:
modules_install
$make -C /lib/modules/`uname -r`/build modules_install
tips: $KDIR is short of path of the kernel source directory
-C $KDIR make命令会自动改变到这个特殊的kernel source目录
M=$PWD 通知kbuild一个外部模块已经被建立,”M”是这个外部模块(kbuild file)所在的绝对路径
make -C $KDIR M=$PWD [target]
模块默认在这个文件夹生成(哪个?),所有的文件都会在这个文件夹中
同上
同上
仅仅删除在模块目录中生成的所有文件
从来没用过
最简单的例子:
obj-m := <module_name>.o
这kbuild系统将会根据
如果模块是由多个文件构建而来,则是一下格式
<module_name>-y := <src1>.o <src2>.o
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