一、內核棧
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,不要使用過大的變量(如大的數組),否則溢出死機。
需要C/C++ Linux伺服器架構師學習資料私信「資料」(資料包括C/C++,Linux,golang技術,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒體,CDN,P2P,K8S,Docker,TCP/IP,協程,DPDK,ffmpeg等),免費分享
驅動裡的全局變量,局部變量,static局部變量放在哪裡了?
這些變量可以被不同的應用程式共享嗎?
如下:
/********************************base.c**************/ include <linux/delay.h> include <linux/kernel.h> include <linux/init.h> include <linux/fs.h> include <linux/time.h> include <linux/moduleparam.h> include <linux/errno.h> include <linux/cdev.h> include <linux/list.h> include <asm/uaccess.h> include <asm/unistd.h> ifdef DEBUG 34; DBG(%s, %s(), %d): &else endif 34;misc_test_dev&define NUM_BYTES 32 int a=1;ssize_t misc_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos) { return 0; //return the bytes quantity have copied} ssize_t misc_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) { char *kbuf=kmalloc(1,GFP_KERNEL); *kbuf++; printk(&34;,*kbuf,kbuf); int b=2; b++; printk(&34;,b,&b); static int c=2; c++; printk(&34;,c,&c); a++; printk(&34;,a,&a); return count ; //return the bytes quantity have copied} static int misc_release(struct inode *inode, struct file *filp) {DBG(&34;); return 0; } static int misc_open(struct inode *inode, struct file *filp) { DBG(&34;); return 0; } static struct file_operations dev_fops = { .owner = THIS_MODULE, .open = misc_open, .read = misc_read, .write = misc_write, .release= misc_release, }; static struct miscdevice misc = { .minor = MISC_DYNAMIC_MINOR, .name = DEVICE_NAME, .fops = &dev_fops, }; static int __init dev_init(void) { int ret; ret = misc_register(&misc); DBG (DEVICE_NAME&34;); return ret; } static void __exit dev_exit(void) { DBG (DEVICE_NAME&34;); misc_deregister(&misc); } module_init(dev_init); module_exit(dev_exit); MODULE_LICENSE(&34;); MODULE_AUTHOR(&34;);
/********************************readtest.c**************/ include <unistd.h> include <sys/types.h> include <sys/ioctl.h> include <linux/fs.h> include <string.h> ifdef DEBUG 34; DBG(%s, %s(), %d): &else endif 34;open file & insmod base.ko DBG(/work/linux/test/base.c, dev_init(), 98): misc_test_dev init[root@FriendlyARM /] [root@FriendlyARM /] //ctrl+c斷掉,然後再次執行一次[root@FriendlyARM /]include<stdio.h>include<stdlib.h>include<pthread.h> ifdef DEBUG 34;%s(),%d:&else endif pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;pthread_cond_t cond = PTHREAD_COND_INITIALIZER; int count = 0; void *decrement(void *arg) { DBG(&34;,count); pthread_mutex_lock(&mutex); DBG(&34;,count); if (count == 0) pthread_cond_wait(&cond, &mutex); count--; DBG(&34;,count); pthread_mutex_unlock(&mutex); DBG(&34;,count); return NULL;} void *increment(void *arg) { DBG(&34;,count); pthread_mutex_lock(&mutex); DBG(&34;,count); count++; DBG(&34;,count); if (count != 0) pthread_cond_signal(&cond); DBG(&34;,count); pthread_mutex_unlock(&mutex); DBG(&34;,count); return NULL;} int main(int argc, char *argv[]) { pthread_t tid_in, tid_de; pthread_create(&tid_de, NULL, (void*)decrement, NULL); sleep(2); pthread_create(&tid_in, NULL, (void*)increment, NULL); sleep(5); pthread_join(tid_de, NULL); pthread_join(tid_in, NULL); pthread_mutex_destroy(&mutex); pthread_cond_destroy(&cond); return 0;}
等待線程:
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釋放鎖