看到一篇好的!文章,转过来。
如果你认为自己是互联网中的一员(业内人士或普通用户),想想自己是不是每天都徘沉溺于各种社区和同行、朋友、同学互动?是不是时时不忘阅读各种新鲜、热辣、搞笑的文章?是不是频繁参加业内各种各样的研讨会、聚会活动,有时候还会为没赶上而懊恼?真的需要这些吗?自己从这里面真正得到收获了吗?
本文是从 What I Wish Someone Had Told Me 4 Years Ago 翻译而来,作者是一个创业者,之前在微软工作。文章主要讲述了作者对创业、做事、时间管理、面对失败的感悟,以及一些优秀的建议。读罢此文,我觉得有必要和大家一起分享作者的这些经验。文章提到的这些,至少我是比较认同的。当你开始思考这些时,你会发现,原来自己一直都陷入了一个误区——看别人表演。
嗯,是时候开始行动了!
就在2007年,我毅然离开了微软,加入了创业者的队伍。像很多第一次创业的人一样,我对这种冒险非常的兴奋。同样也跟很多第一次创业的人一样,我茫然没有头绪。
我参加各种活动,聚会,研讨会,和西雅图本地的创业社区密切交往。当我到了硅谷后,我发现这里有更多的活动,聚会,更多的研讨会。在这个创业生态系统里,一切很忙、很活跃,我收获了大量的人们共享出来的知识和体验,我如饥似渴的享用着。
我还满腔热情的看了很多的博客,视频和书籍。活动、聚会、研讨会中人们分享和讨论的都是非常好的主题。
我甚至还加入了一个创业孵化机构!
直到决定开办自己的公司时,我才意识到,所有我的阅读、观看、参加的活动实际上没有给我带来任何的用处。我是认真的。完全没有任何用处。大部分我学到的东西都想不起来了,剩下一点能记住的也很少能应用到我现在的处境里。学习他人的经验和成功对我就像是在吃快餐,像是吃那些味道很好的垃圾食品,让我膨胀,让我自满。抱歉我在泼冷水,但这是事实。
起初,我努力把我学到的东西应用到我自己的问题里。不灵。这不可思议的时刻真的到来了,我平静的接受了这个事实:我浪费了大量的时间去学了一些根本不需要的东西,我相信有人说过的一句话正是在嘲笑我的这些行为:所有的这些活动,研讨会,博客文章都只是用来多拖延你一天立即行动的另一个借口。我默默的接受这个事实,以一个新手的心情往前走,沿着这个方向,我相信我将会理解出什么才是我需要的。
所有的变化由此而来。
我们每个人身上都有一种东西,想在这种存在着不确定性、具有风险的创业冒险活动中创造,成就,前进。但我们还有另外一种东西,每个人都希望能感到确定,可靠,让我们能做出正确的决策,让我们在这条道路上不至于失败、使自己受伤。矛盾冲突就是从此产生的。
可是这些博客,活动,访谈并不能真正的消解这些矛盾。只是暂时的,它让我知道,有很多人在做和我同样的事情,让我放松。去创业是让我走出我的安逸环境,而我所做的只是从一个安逸环境跳到另外一个安逸环境。你知道吗?我就职于一个不错的公司!
一天,我反省一下我目前的状况,发现自己忙于很多事情,唯独没有把时间用于自己的产品上。几个月后,我终于鼓足勇气对自己说:这唯一重要的事情是真正的坐下来去做事。
别误会。我觉得有些博客和研讨会还是有价值的。但除非你真正的去实施什么事情、给你所学所扩展的关系网创造一个用武之地,你就是在浪费你的宝贵时间。
下面就是一些帮助了我去克服这“创业困惑综合征”的东西:
1、我数周内不再阅读创业新闻和博客,我意识到对于我的产品我不缺任何东西。至于谁又获得了融资,谁被收购了,以及为什么在Google Chrome的竞争下IE丧失了它的市场份额,这跟我没有任何关系。我唯一要关心的人是客户,我唯一要关心的事情是他们的需求和愿望、如何提供他们最有价值的东西。
2、我数月不去参加那些创业相关的活动,而且开始通过咖啡和酒去交接朋友。每月我仍可能会去参加一两个活动,但那只是为了娱乐。我不再迷惑于为了成为一个企业家而且参加那些创业相关的活动。
3、我通过小项目来实践学习。我把一些想法细化成容易管理的细目,给自己设定期限去完成它们。项目和试验品是神奇的教学工具,因为你在学习你想要的,你在获得第一手资料。就像Keynotopia这个项目极大的帮助了我产生灵感,形成思路,我可以看见它,和它交互,展示给别人——这就是我首先要把它做出来的原因!有时一些小项目还可以让你获得不少收入。
4、每走一步,我都准备好一个问题清单,它能让我知道下一步该往哪里走。是该去获得更多的访问量?改进产品?还是在不提高访问量的情况下提高收入?我整理出最好的问题,然后研究它,咨询人们,然后把获得的答案立即付诸于行动。这些信息我都不会让它们在我的大脑里转的太久。
5、这是我的最爱:我更多的恐惧是产生于没有去行动,而不是相反的害怕去行动。我认识到,晚一天我没有让客户接受我的方案,竞争对手就多一天的机会比我先达到客户要求。我甚至设想到了如果我不能行动起来,最终将会看到最可怕的噩梦:从办公室又回到密尔顿,在Innotech的小隔间里饱食终日,拿着那个红色的订书机,等着下一次的发薪日。这正是我需要的充满魔力的紧迫感。
6、我第一是要把事情完成,然后才是把事情办对。我知道(深受教训),做事的劲头重要无比。如果你在得到一个想法后不能立即付诸实施,最终很有可能的结局是这个想法被束之高阁。如今不论何时我得到了一个想法,我会盯着它让它成为现实,让它变成实际。我立即行动,虽然方式不成熟,但之后想办法改进,这样就学会了自己真正需要的东西。
7、面对现实:如果你不走出你的安逸环境、动手去干,什么事情都不会发生。等待再等待,罕有行动。
我想留给你们一句改变了我的生活的名言:成功的人并不是一定比别人更有才智和更幸运。他们只是在不断的尝试、不断的失败,直到成功。
不要做想象中的企业家,用行动和成果成为企业家。
不知道各位是否体会到了作者的用心,他用他的经历告诉我们,只有真正坐下来做事,才是取得成功的唯一途径。说,没有用;行动,才是最重要的。
与君分享
目前我能想到的是做一个有关咨询的网站,目标是社会中产阶级,利用自己的优势去帮助 他们更好的理解国家政策法规、海外的投资机会,应该不是什么难的项目。
从邮件列表开始
原文地址 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