从static关键字说起
来源:互联网 发布:七天网络阅卷app 编辑:程序博客网 时间:2024/05/20 06:50
为什么linux的驱动方法都加static关键字呢?带着这个疑问,我有了下边的一些收获。
ok,从最基本的static关键字在c语言中的作用说起吧。
在c语言中static关键字用来描述变量和函数有不用的作用,先来看函数:
我写了两个文件main.c和b.c:
//b.c中定义了一个static修饰的方法 static void staticTest(){ printf("static test is running..."); }//main.c中调用 void main(){ staticTest(); }
这种情况下调用会出错,原因就是用static关键字修饰的函数只在本文件内有效(文件作用域)。 可以说这个staticTest函数属于b.c这个文件。
当然用static来修饰一个全局变量也是相同的结果,但是如果用static修饰一个局部变量会有什么结果?我在main.c中定义了两个方法:
void main(){ run(); run(); run2(); run2(); }static void run(){ int x = 2; x++; printf("x is %d\n",x); }void run2(){ static x = 2; x++; printf("x is %d\n",x); }
运行结果:
x is 3;x is 3;x is 3;x is 4;
也就是说,static修饰的局部变量不管函数被调用多少次,这个局部变量只有一份。
为什么会这样,这个得分析一下内存模型。这是linux进程的内存模型:
先了解几个概念:
栈:从高地址向低地址扩展
堆:从低地址向高地址扩展(因为你不知道堆和栈具体的空间大小,这样类似双端队列的做法可以充分利用空间)
(忽然想到以前从数据库中取出的数据作为数组存在heap中导致内存溢出,以前以为是stack溢出,现在明白是heap溢出)
bss segment:未初始化段,看图识字。
data segment:初始化段,看图识字。
Text segment:也叫code segment,放些只读的数据,我理解常量也放这里。(一直搞不懂常量区到哪??)
好的,开始:起初,当程序以二进制的形式被加载到内存中,stack中什么也没有,bss中被清零,data中初始化全局变量,text中存放一些只读(rodata)的常量。
当有函数被调用的时候,就会生成一个栈帧(stack frame):
栈帧:一个函数执行的环境:函数参数、函数的局部变量、函数执行完后返回到哪里等等。
将栈帧插入到栈中,例如运行同一个函数两次就会有两个栈帧被插入,栈帧中的非静态局部变量的值是从常量区中取得,就是说,每个栈帧都有属于它的一份局部变量,但是:静态局部变量的值只有一份,所有栈帧共用一个值。
我说的有点乱,看个例子(来自网上):
//main.cpp int a = 0; 全局初始化区 char *p1; 全局未初始化区 main() { int b; //栈 char s[] = "abc"; //栈 char *p2; //栈 char *p3 = "123456"; //123456\0在常量区,p3在栈上。 static int c =0; //全局(静态)初始化区 p1 = (char *)malloc(10); p2 = (char *)malloc(20); //分配得来得10和20字节的区域就在堆区。 strcpy(p1, "123456"); //123456\0放在常量区,编译器可能会将它与p3所指向的"123456"优化成一个地方。 }
可以看到静态变量的值不存在常量区。常量区放的是只读的数据(供栈帧从中复制值,复制后值不变),静态变量及其值都是存储在bss和data段,可以在程序运行时修改的(栈帧不复制,直接使用)。
写到这里我又想起一个困扰我很久的问题(原谅我是个Java程序员):
String str = new String("abc");//存放在堆中 String str = "abc";//先在栈中创建一个String类的对象指针str,然后查找文字中有没有存放"abc",如果没有,则将"abc"存放进文字常量区,并令str指向"abc",如果已经有"abc"则直接令str指向"abc"
ok,关于static关键字在c语言中的作用就讲到这里,关于static关键字在c++中的用法(c++中有class来划定边界,因此static有public、private之分),有时间再写。
回归起初的问题,为什么linux驱动函数都要交static关键字,为了不让用户调用, 我们知道linux有系统空间和用户空间,而驱动就是工作再系统空间,和内核是同一级别, 内核大部分都是驱动,而linux内核也只有一个main函数(起初操作系统只有一个init进程,其他进程由它生成),也就是说加上static之后,内核可以调用,而用户不可以调用。
这里有个问题:static关键字修饰函数只在文件内有效,我的理解就是b.c中有效,那么为什么linux 内核函数可以调用呢??
- 从static关键字说起
- 广语言“广译”从javascript的关键字翻译说起
- 从This Handler class should be static or leaks might occur!警告说起
- 从Object_oriented 说起
- 从AFX_MANAGE_STATE(AfxGetStaticModuleState())说起
- 从“芙蓉姐姐”现象说起
- 不知从何说起
- 从jira说起
- 从AFX_MANAGE_STATE(GetStaticModuleState())说起
- 从辞职说起
- 从"爱因斯坦圆"说起
- 从PDCA说起
- 从被点到说起......
- 从大乘“六度法”说起
- 从AFX_MANAGE_STATE(AfxGetStaticModuleState())说起
- 从Proxy.newProxyInstance说起
- 从中医经络说起
- 从jira说起
- 多线程同步与互斥
- android环境的搭配
- How to hide application icon?
- 保护眼睛:把白皑皑的窗口变成淡淡的绿
- ADO.NET数据库SQL操作步骤
- 从static关键字说起
- 移植最新版WordPress 3.5.1 到SAE上,可以上传附件
- WINDOW_JAVA环境变量设置
- ubuntu12.0.4 安装eclipse
- Android 4.1源码编译找不到资源文件解决办法
- linux网络编程之System V 信号量(一):封装一个信号量集操作函数的工具
- 商务通去掉四周的边框 好像定制一样实现方法
- 做出一些自己能做的贡献
- tomcat 如何解析Resource数据源