#函数
__task_pid_nr_ns(struct task_struct *task,enum pid_type type,struct pid_namespace *ns) #文件包含 #include<linux/sched.h> #函数定义 ##在内核源代码的位置 linux-3.2.64/kernel/pid.c ##函数定义格式:
#函数功能描述 此函数用于获取进程的进程号,但应该满足以下几个条件。 1.参数type如果不等于PIDTYPE_PID,则参数task用其所属任务组的第一个任务赋值,否则保持task不变。
2.此进程是参数task任务描述符的进程。
3.保证进程描述符和pid_namespaces和参数ns相同。
#参数补充(未写)
#举例
结合以前的知识,写出Makefile,执行
make
然后,键入
insmod __task_pid_nr_ns.ko
这时一般终端就会有消息产出,如果没有可以接着使用 __dmesg -c__命令 ##终端信息
Message from syslogd@debian at Nov 21 15:28:12 ... kernel:[ 458.244921] into __task_pid_nr_ns_init. Message from syslogd@debian at Nov 21 15:28:12 ... kernel:[ 458.244971] the pid of the find_get_pid is :2915 Message from syslogd@debian at Nov 21 15:28:12 ... kernel:[ 458.244980] the result of __task_pid_nr_ns is :2915 Message from syslogd@debian at Nov 21 15:28:12 ... kernel:[ 458.244988] the result of kernel_thread is :2915 Message from syslogd@debian at Nov 21 15:28:12 ... kernel:[ 458.244995] the pid of current thread is :2914 Message from syslogd@debian at Nov 21 15:28:12 ... kernel:[ 458.245002] out __task_pid_nr_ns_init. Message from syslogd@debian at Nov 21 15:28:12 ... kernel:[ 458.245964] in the kernel thread function dmesg -c dmesg: klogctl failed: 不允许的操作 yubo@debian:~/linux/process$
#find_get_pid() 定义:struct pid *find_get_pid(int nr) ##功能 此函数根据提供的进程号获取对应的进程描述符,并使进程描述符的count的值加1即此进程的用户数加1
##参数说明 nr即为进程号 ##返回参数 返回与参数提供的进程号对应的进程描述符,进程描述符定义如下:
##find_get_pid()应用举例
##输出结果
Message from syslogd@debian at Nov 23 05:42:16 ... kernel:[ 3162.689851] into the find_get_pid_init. Message from syslogd@debian at Nov 23 05:42:16 ... kernel:[ 3162.689863] the count of the pid is :2 Message from syslogd@debian at Nov 23 05:42:16 ... kernel:[ 3162.689864] the level of the pid is :0 Message from syslogd@debian at Nov 23 05:42:16 ... kernel:[ 3162.689866] the pid of the find_get_pid is :3554 Message from syslogd@debian at Nov 23 05:42:16 ... kernel:[ 3162.689867] the result of the kernel_thread is :3554 Message from syslogd@debian at Nov 23 05:42:16 ... kernel:[ 3162.689868] out find_get_pid_init. Message from syslogd@debian at Nov 23 05:42:16 ... kernel:[ 3162.690635] in the kerenl thread function!
看到一篇好的!文章,转过来。
如果你认为自己是互联网中的一员(业内人士或普通用户),想想自己是不是每天都徘沉溺于各种社区和同行、朋友、同学互动?是不是时时不忘阅读各种新鲜、热辣、搞笑的文章?是不是频繁参加业内各种各样的研讨会、聚会活动,有时候还会为没赶上而懊恼?真的需要这些吗?自己从这里面真正得到收获了吗?
本文是从 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文件中,一行一个