linux内核栈,内核同步,用户空间线程同步

转载:http://blog.csdn.net/opencpu/article/details/8136343

1.内核栈




1.每当创建一个进程(主线程),用户线程,内核线程时,内核都会给这个进程或线程动态创建一个内核栈,在内核空间,换存在cache中。内核栈里有个thread_info指针,指向task_struct结构体(cpu根据这个来调度,所以可以实现调度的基本单位是线程)。
2.进程用户栈:创建一个用户进程(主线程)时,需要创建一个mm_struct,使其task_struct中的mm指针指向此mm_struct
3.用户线程和其他线程共享用户栈“:创建一个用户线程时,使其task_struct中的mm指针指向一个已存在的mm_struct。这些线程共用一个进程地址空间。 但是同一个进程的多个线程有自己的调用栈,自己的寄存器环境,自己的线程本地存储
4.内核线程没有用户栈:创建一个内核线程时,使其task_struct中的mm指针为空。

5.对于进程地址空间,用户栈存放局部变量等东东,数据段.data存放全局变量和static变量(static局部变量)
6.对于内核地址空间(0xc000 0000以上的),其是不是也分为数据段代码段呢?是不是数据段也存放着内核的全局变量和statci变量呢?
有一点可以知道,内核空间有n多个内核栈,有多少线程就有多少内核栈,但每个栈都很小(不像进程空间的用户栈,一个进程只有一个用户栈,但很大)

7.从用户态进入内核是什么意思?
先看  进程上下文 中断上下文 / 用户空间 内核空间
比如一个进程在他的地址空间(0xc000 0000 以下)里面玩的好好的,突然要调用一个函数(系统调用),而这个函数位于地址0xc666 6666(整个内核地址空间即0xc000 0000以上有什么函数和符号,其地址可以理解为都是已经确定好的),于是就要跑到0xc666 6666地址去执行,此时算是进入内核态了。在执行0xc666 6666这个函数时,函数里面的局部变量需要保存在这个进程的对应的内核栈里面,内核栈<8KB,不要使用过大的变量(如大的数组),否则溢出死机。


驱动里的全局变量,局部变量,static局部变量放在哪里了?
这些变量可以被不同的应用程序共享吗?
如下:
[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. /********************************base.c**************/      
  2. #include <linux/miscdevice.h>    
  3. #include <linux/delay.h>    
  4. #include <asm/irq.h>    
  5. #include <linux/kernel.h>    
  6. #include <linux/module.h>    
  7. #include <linux/init.h>    
  8. #include <linux/mm.h>    
  9. #include <linux/fs.h>    
  10. #include <linux/types.h>    
  11. #include <linux/time.h>      
  12. #include <linux/timer.h>     
  13. #include <linux/moduleparam.h>    
  14. #include <linux/slab.h>    
  15. #include <linux/errno.h>    
  16. #include <linux/ioctl.h>    
  17. #include <linux/cdev.h>    
  18. #include <linux/string.h>    
  19. #include <linux/list.h>    
  20. #include <linux/gpio.h>    
  21. #include <asm/uaccess.h>    
  22. #include <asm/atomic.h>    
  23. #include <asm/unistd.h>    
  24.   
  25. #define DEBUG    
  26. #ifdef DEBUG      
  27. #define DBG(...) printk(" DBG(%s, %s(), %d): ", __FILE__, __FUNCTION__, __LINE__); printk(__VA_ARGS__)      
  28. #else      
  29. #define DBG(...)      
  30. #endif      
  31.   
  32.   
  33. #define DEVICE_NAME "misc_test_dev"    
  34. int ret;  
  35. #define NUM_BYTES 32  
  36.   
  37. int a=1;  
  38. ssize_t misc_write(struct file *filp, const char __user *buf, size_t count,  loff_t *f_pos)    
  39. {         
  40.   
  41.     return 0; //return the bytes quantity have copied  
  42. }    
  43.   
  44. ssize_t misc_read(struct file *filp, char __user *buf, size_t count,  loff_t *f_pos)    
  45. {    
  46.     char *kbuf=kmalloc(1,GFP_KERNEL);  
  47.     *kbuf++;  
  48.     printk("*kbuf=%d,kbuf=0x%x\n",*kbuf,kbuf);  
  49.   
  50.   
  51.     int b=2;  
  52.     b++;  
  53.     printk("b=%d,&b=0x%x\n",b,&b);  
  54.   
  55.     static int c=2;  
  56.     c++;  
  57.     printk("c=%d,&c=0x%x\n",c,&c);  
  58.   
  59.     a++;  
  60.     printk("a=%d,&a=0x%x\n",a,&a);  
  61.   
  62.   
  63.     return count ;  //return the bytes quantity have copied  
  64. }    
  65.   
  66.   
  67. static int misc_release(struct inode *inode, struct file *filp)    
  68. {  
  69. DBG("release \n");     
  70. return 0;    
  71. }    
  72.   
  73. static int misc_open(struct inode *inode, struct file *filp)    
  74. {       
  75. DBG("open \n");    
  76. return 0;    
  77. }    
  78.   
  79.   
  80. static struct file_operations dev_fops = {    
  81. .owner  =   THIS_MODULE,    
  82. .open   =   misc_open,    
  83. .read   =   misc_read,    
  84. .write  =   misc_write,    
  85. .release=   misc_release,    
  86. };    
  87.   
  88. static struct miscdevice misc = {    
  89. .minor = MISC_DYNAMIC_MINOR,    
  90. .name = DEVICE_NAME,    
  91. .fops = &dev_fops,    
  92. };    
  93.   
  94. static int __init dev_init(void)    
  95. {    
  96. int ret;    
  97. ret = misc_register(&misc);    
  98. DBG (DEVICE_NAME"\tinit\n");    
  99. return ret;    
  100. }    
  101.   
  102. static void __exit dev_exit(void)    
  103. {    
  104. DBG (DEVICE_NAME"\texit\n");    
  105. misc_deregister(&misc);    
  106. }    
  107.   
  108. module_init(dev_init);    
  109. module_exit(dev_exit);    
  110. MODULE_LICENSE("GPL");    
  111. MODULE_AUTHOR("Song.");    

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. /********************************readtest.c**************/    
  2. #include <stdio.h>    
  3. #include <unistd.h>    
  4. #include <stdlib.h>    
  5. #include <sys/types.h>    
  6. #include <sys/stat.h>    
  7. #include <sys/ioctl.h>    
  8. #include <fcntl.h>    
  9. #include <linux/fs.h>    
  10. #include <errno.h>    
  11. #include <string.h>   
  12.    
  13. #define DEBUG  
  14. #ifdef DEBUG    
  15. #define DBG(...) fprintf(stderr, " DBG(%s, %s(), %d): ", __FILE__, __FUNCTION__, __LINE__); fprintf(stderr, __VA_ARGS__)    
  16. #else    
  17. #define DBG(...)    
  18. #endif    
  19. #define NUM_BYTES 32  
  20. int main(int argc,char* argv[])    
  21. {       
  22.   
  23.     int fd = open(argv[1], 0);    
  24.     if (fd < 0) {    
  25.         perror("open file ");    
  26.         return 1;    
  27.     }    
  28.   
  29.     char buf;  
  30.         int len = read(fd, &buf, 1);   
  31.   
  32. pause();  
  33.     close(fd);    
  34. }    
在tiny6410上测试:
[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. [root@FriendlyARM /]# insmod base.ko   
  2.  DBG(/work/linux/test/base.c, dev_init(), 98): misc_test_dev    init  
  3. [root@FriendlyARM /]# lsmod   
  4. base 1861 0 - Live 0xbf024000//模块所在地址  
  5. fa_cpu_pfn 715 0 - Live 0xbf000000 (P)  
  6. [root@FriendlyARM /]#   
  7. [root@FriendlyARM /]# ./readtest /dev/misc_test_dev   
  8.  DBG(/work/linux/test/base.c, misc_open(), 75): open   
  9. *kbuf=70,kbuf=0xcd654901  
  10. b=3,&b=0xcd439f4c  
  11. c=3,&c=0xbf0242ac  
  12. a=2,&a=0xbf0242b0  
  13. ^C DBG(/work/linux/test/base.c, misc_release(), 69): release   
  14.   
  15. [root@FriendlyARM /]# //ctrl+c断掉,然后再次执行一次  
  16. [root@FriendlyARM /]# ./readtest /dev/misc_test_dev   
  17.  DBG(/work/linux/test/base.c, misc_open(), 75): open   
  18. *kbuf=76,kbuf=0xcd6546a1  
  19. b=3,&b=0xcd439f4c  
  20. c=4,&c=0xbf0242ac   
  21. a=3,&a=0xbf0242b0   
  22. ^C DBG(/work/linux/test/base.c, misc_release(), 69): release   
  23.   
  24. [root@FriendlyARM /]#   
从上面的例子可以看出
kbuf的地址每次都不一样,可能位于内核的某个slab空间里面(不单独为某个进程所有)
局部变量b位于进程的内核栈里面,0xcd439f4c,每个进程都有独立的b

static 局部变量c变成4说明可以被共享不随着进程的消失而销毁,c应该不是保存在进程的内核栈里面,因为进程内核栈随着进程的消失会销毁
全部变量a变成3说明可以被共享,a也应该不是保存在进程的内核栈里面,
那么a和c保存在哪里呢?
a和c的地址位于0xc000 0000 以下,,内核里的全局变量怎么跑到用户空间了?
看一下模块加载到的地址0xbf024000,也是0xc000 0000以下,和a,c的地址很接近,似乎有点关系
待续

51的局部变量和全局变量:
cpu arch之risc, cisc ,von-neumann,harvard ,modified harvard



2.用户空间同步

http://blog.csdn.net/zzran/article/details/8830213
[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. #include<stdio.h>  
  2. #include<sys/types.h>  
  3. #include<stdlib.h>  
  4. #include<unistd.h>  
  5. #include<pthread.h>  
  6.   
  7. #define DEBUG  
  8.   
  9. #ifdef DEBUG  
  10.     #define DBG(...)  printf("%s(),%d:", __FUNCTION__,__LINE__); printf(__VA_ARGS__)  
  11. #else  
  12.     #define DBG(...)    
  13. #endif  
  14.   
  15.   
  16. pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;  
  17. pthread_cond_t  cond  = PTHREAD_COND_INITIALIZER;  
  18.   
  19. int count = 0;  
  20.   
  21. void *decrement(void *arg) {  
  22.   
  23.     DBG("count=%d\n",count);  
  24.     pthread_mutex_lock(&mutex);  
  25.     DBG("count=%d\n",count);  
  26.   
  27.     if (count == 0)  
  28.         pthread_cond_wait(&cond, &mutex);  
  29.     count--;  
  30.   
  31.     DBG("count=%d.\n",count);  
  32.     pthread_mutex_unlock(&mutex);  
  33.     DBG("count=%d.\n",count);  
  34.     return NULL;  
  35. }  
  36.   
  37. void *increment(void *arg) {  
  38.   
  39.     DBG("count=%d\n",count);  
  40.     pthread_mutex_lock(&mutex);  
  41.     DBG("count=%d\n",count);  
  42.     count++;  
  43.     DBG("count=%d\n",count);  
  44.   
  45.     if (count != 0)  
  46.         pthread_cond_signal(&cond);  
  47.   
  48.     DBG("count=%d\n",count);  
  49.     pthread_mutex_unlock(&mutex);  
  50.     DBG("count=%d\n",count);  
  51.     return NULL;  
  52. }  
  53.   
  54. int main(int argc, char *argv[]) {  
  55.     pthread_t tid_in, tid_de;  
  56.     pthread_create(&tid_de, NULL, (void*)decrement, NULL);  
  57.     sleep(2);  
  58.     pthread_create(&tid_in, NULL, (void*)increment, NULL);  
  59.     sleep(5);  
  60.     pthread_join(tid_de, NULL);  
  61.     pthread_join(tid_in, NULL);  
  62.     pthread_mutex_destroy(&mutex);  
  63.     pthread_cond_destroy(&cond);  
  64.     return 0;  
  65. }  

 等待线程:

     pthread_cond_wait前使用pthread_mutex_lock先加锁

     pthread_cond_wait内部会解锁,然后等待条件变量被其它线程激活
     pthread_cond_wait被激活后会再自动加锁

     pthread_cond_wait返回之后需要使用pthread_mutex_unlock释放锁
激活线程:
     pthread_cond_signal前使用pthread_mutex_lock加锁(和等待线程用同一个锁)
     pthread_cond_signal发送信号
     pthread_cond_signal返回之后需要使用pthread_mutex_unlock释放锁

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值