# 一個(gè)驅(qū)動(dòng)程序的角色是提供機(jī)制,而不是策略 2010-11-15 09:26 小默
“一個(gè)驅(qū)動(dòng)程序的角色是提供機(jī)制,而不是策略。”--ldd3
機(jī)制:提供什么能力
策略:如何使用這些能力
機(jī)制和策略由軟件不同部分,或完全不同的軟件實(shí)現(xiàn)。
比如第一次實(shí)習(xí)時(shí):
我們這邊負(fù)責(zé)寫驅(qū)動(dòng),只關(guān)注實(shí)現(xiàn)什么功能,怎么實(shí)現(xiàn)這樣功能,這是機(jī)制。我們可以直接在設(shè)備管理器中安裝卸載,或者用命令行安裝卸載使用等,隨意,也就是開發(fā)過程完全不考慮策略。
等開發(fā)進(jìn)行到了一定階段,又招了另外一名同學(xué)負(fù)責(zé)界面,這是策略。用戶怎么使用這個(gè)驅(qū)動(dòng),操作界面是怎樣的,是由他來負(fù)責(zé)的。
不知道是不是這個(gè)意思O(∩_∩)O~~ 回復(fù) 更多評(píng)論 刪除評(píng)論 修改評(píng)論
# makefile寫法 2010-11-15 17:14 小默
對(duì)于單個(gè).c文件的hello world例子:
obj-m := hello.o
從目標(biāo)文件hello.o簡(jiǎn)歷一個(gè)模塊hello.ko
如果模塊來自兩個(gè)源文件file1.c和file2.c:
obj-m := module.o
module-objs := file1.o file2.o
上面的命令,必須在內(nèi)核系統(tǒng)上下建立文中被調(diào)用
-----
在任意當(dāng)前工作目錄中,需要在makefile中指明源碼樹的路徑。
ifneq ($(KERNELRELEASE),)
obj-m := hello.o
else
KERNELDIR ?= /lib/modules/$(shell uname -r)/build //TODO 不是在源碼樹中么/(ㄒoㄒ)/~~
PWD := $(shell pwd)
default:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
endif
創(chuàng)建一個(gè)模塊需要調(diào)用兩次上面的makefile
第一次:沒有設(shè)置變量KERNELRELEASE,通過已安裝模塊目錄中的符號(hào)鏈接指回內(nèi)核建立樹;然后運(yùn)行default中的make命令,第二次使用makefile
第二次:已經(jīng)設(shè)置了變量KERNELRELEASE,直接obj-m := hello.o創(chuàng)建模塊 回復(fù) 更多評(píng)論 刪除評(píng)論 修改評(píng)論
# 加載和卸載模塊 2010-11-15 17:57 小默
modprobe實(shí)現(xiàn)和insmod一樣加載模塊到內(nèi)核的功能
不同的是,加載前會(huì)檢查模塊中是否有當(dāng)前內(nèi)核中沒有定義的symbol,如果有,在模塊搜索路徑中尋找其它模塊是否含有上面的symbol,有的話,自動(dòng)加載關(guān)聯(lián)模塊
insmod對(duì)于這種情況,會(huì)報(bào)錯(cuò)unresolved symbols
查看當(dāng)前加載模塊:
lsmod
cat /proc/modules
回復(fù) 更多評(píng)論 刪除評(píng)論 修改評(píng)論
# 如果你的模塊需要輸出符號(hào)給其他模塊使用 2010-11-15 18:12 小默
EXPORT_SYMBOL(name);
EXPORT_SYMBOL_GPL(name); 回復(fù) 更多評(píng)論 刪除評(píng)論 修改評(píng)論
# 模塊參數(shù) 2010-11-15 18:40 小默
說10次hello,Mom
# insmod hellop howmany=10 whom="Mom"
--
static char *whom = "world"; //必須給默認(rèn)值
static int howmany = 1;
module_param(howmany, int, S_IRUGO);
module_param(whom, charp, S_IRUGO);
--
S_IRUGO 允許所有人讀
S_IRUGO | S_IWUSR 允許所有人讀,允許root改變參數(shù)
如果參數(shù)被sysfs修改,不會(huì)通知模塊。不要使參數(shù)可寫,除非準(zhǔn)備好檢測(cè)參數(shù)改變。
--
數(shù)組參數(shù):
module_param_array(name, type, num, perm); 回復(fù) 更多評(píng)論 刪除評(píng)論 修改評(píng)論
# 設(shè)備主次編號(hào) 2010-11-16 13:24 小默
$ ls -l /dev
...
crw-rw---- 1 vcsa tty 7, 132 Nov 15 17:16 vcsa4
crw-rw---- 1 vcsa tty 7, 133 Nov 15 17:16 vcsa5
crw-rw---- 1 vcsa tty 7, 134 Nov 15 17:16 vcsa6
crw-rw---- 1 root root 10, 63 Nov 15 17:16 vga_arbiter
drwxr-xr-x 2 root root 80 Nov 15 17:16 vg_colorfulgreen
crw-rw-rw- 1 root root 1, 5 Nov 15 17:16 zero
...
輸出第一列是c的是字符設(shè)備,第一列b塊設(shè)備
修改日期前的兩個(gè)數(shù)字。
第一個(gè)是主設(shè)備編號(hào):標(biāo)識(shí)設(shè)備相連的驅(qū)動(dòng)
第二個(gè)是次設(shè)備編號(hào):決定引用哪個(gè)設(shè)備
-------
設(shè)備編號(hào)的內(nèi)部表示
dev_t 在<linux/types.h>中定義,32位,12位主編號(hào),20位次編號(hào)。
獲得一個(gè)dev_t的主或次編號(hào):<linux/kdev_t.h>
MAJOR(dev_t dev);
MINOR(dev_t dev);
將主次編號(hào)轉(zhuǎn)換成dev_t:
MKDEV(int major, int minor);
--------
分配和釋放設(shè)備編號(hào)
建立一個(gè)字符驅(qū)動(dòng)時(shí),做的第一件事就是獲取一個(gè)或多個(gè)設(shè)備編號(hào)使用:
<linux/fs.h>
int register_chrdev_region(dev_t first, unsigned int count, char *name);
first要分配的起始設(shè)備編號(hào)
count請(qǐng)求的連續(xù)設(shè)備編號(hào)的總數(shù)
name連接到這個(gè)編號(hào)范圍的設(shè)備的名字,會(huì)出現(xiàn)在/proc/devices和sysfs中
成功返回0,出錯(cuò)返回負(fù)的錯(cuò)誤碼。
如果事先不知道使用哪個(gè)設(shè)備編號(hào),使用下面函數(shù),內(nèi)核會(huì)分配一個(gè)主設(shè)備編號(hào):
int alloc_chrdev_region(dev_t *dev, unsigned int firstminor, unsigned int count, char *name);
dev是一個(gè)輸出參數(shù),返回分配范圍的第一個(gè)數(shù)
firstminor請(qǐng)求第一個(gè)要用的次編號(hào),常是0
設(shè)備編號(hào)的釋放:
void unregister_chrdev_region(dev_t first, unsigned int count); 回復(fù) 更多評(píng)論 刪除評(píng)論 修改評(píng)論
# scull安裝腳本 2010-11-16 13:57 小默
腳本scull_load:
1 #!/bin/sh
2 module="scull"
3 device="scull"
4 mode="664"
5
6 # invoke insmod with all arguments we got
7 # and use a pathname, as newer modutils don't look in. by default
8 /sbin/insmod ./$module.ko $* || exit 1 # 插入模塊,使用獲取的所有參數(shù)($*)
9
10 # remove stale nodes刪除無效的節(jié)點(diǎn),不能刪除device0,device1,device2...阿。。TODO
11 rm -f /dev/${device}[0-3]
12
13 major=$(awk "\\$2==\"$module\" {print \\$1}" /proc/devices) #TODO 沒有搞明白
14 mknod /dev/${device}0 c $major 0 #創(chuàng)建4個(gè)虛擬設(shè)備
15 mknod /dev/${device}1 c $major 1
16 mknod /dev/${device}2 c $major 2
17 mknod /dev/${device}3 c $major 3
18
19 # give appropriate group/permissions, and change the group.
20 # Not all distributions have staff, some have "wheel" instead. #TODO 神馬意思?
21 group="staff"
22 grep -q '^staff:' /etc/group || group="wheel"
23 # 改變?cè)O(shè)備的組和模式。腳本必須以root運(yùn)行,但設(shè)備使用可能需要其它用戶寫。
24 chgrp $group /dev/${device}[0-3]
25 chmod $mode /dev/${device}[0-3]
26
回復(fù) 更多評(píng)論 刪除評(píng)論 修改評(píng)論
# file_operations結(jié)構(gòu) 2010-11-16 15:24 小默
一些處理文件的回調(diào)函數(shù)
1 // init file_operations
2 struct file_operations scull_fops = {
3 .owner = THIS_MODULE,
4 .llseek = scull_llseek,
5 .read = scull_read,
6 .write = scull_write,
7 .ioctl = scull_ioctl,
8 .open = scull_open,
9 .release = scull_release,
10 }; 回復(fù) 更多評(píng)論 刪除評(píng)論 修改評(píng)論
# 注冊(cè)字符設(shè)備 2010-11-16 15:25 小默
12 // 使用struct scull_dev結(jié)構(gòu)表示每個(gè)設(shè)備
13 // TODO 沒有理解什么意思
14 struct scull_dev {
15 struct scull_qset *data; // pointer to first quantum set
16 int quantum; // the current quantum size
17 int qset; // the current array size
18 unsigned long sizee; //amount of data stored here
19 unsigned int access_key; // used by sculluid and scullpriv
20 struct semaphore sem; // matual exclusion semaphore
21 struct cdev cdev; // 字符設(shè)備結(jié)構(gòu)
22 };
23
24 // 初始化struct cdev,并添加到系統(tǒng)中
25 static void scull_setup_cdev(struct scull_dev *dev, int index)
26 {
27 int err, devno = MKDEV(scull_major, scull_minor + index);
28
29 // TODO 初始化已經(jīng)分配的結(jié)構(gòu). 不是很理解
30 // cdev結(jié)構(gòu)嵌套在struct scull_dev中,必須調(diào)用cdev_init()來初始化cdev結(jié)構(gòu)
31 cdev_init(&dev->cdev, &scull_fops);
32 dev->cdev.owner = THIS_MODULE;
33 dev->cdev.ops = &scull_fops;
34 // 添加到系統(tǒng)中
35 err = cdev_add(&dev->cdev, devno, 1);
36 if(err)
37 printk(KERN_NOTICE "Error %d adding scull%d", err, index);
38 }
回復(fù) 更多評(píng)論 刪除評(píng)論 修改評(píng)論
# system-config-selinux 2010-11-27 02:54 小默
system-config-selinux
什么時(shí)候改了,汗 //TODO 回復(fù) 更多評(píng)論 刪除評(píng)論 修改評(píng)論
# read & write 2010-11-30 22:12 小默
// 表示每個(gè)設(shè)備
struct scull_dev{
struct scull_qset *data; // pointer to first quantum set
int quantum; // the current quantum size - 當(dāng)前量子和量子集大小
int qset; // the current array size - 每個(gè)內(nèi)存區(qū)域?yàn)橐粋€(gè)量子,數(shù)組為一個(gè)量子集
unsigned long size; // amount of data stored here
unsigned int access_key; // used by sculluid and scullpriv
struct semaphore sem; // mutual exclusion semaphore
struct cdev cdev; // char device structure
};
// 量子集,即一個(gè)內(nèi)存區(qū)域的數(shù)組
struct scull_qset{
void **data;
struct scull_qset *next;
};
ssize_t scull_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
{
struct scull_dev *dev = file->private_data;
struct scull_qset *dptr; // 量子集中的第一個(gè)元素
int quantum = dev->quantum, qset = dev->qset; // 當(dāng)前量子和量子集大小
int itemsize = quantum * qset; // listitem中的字節(jié)數(shù)=量子大小*量子集大小
int item, s_pos, q_pos, rset;
ssize_t retval = 0;
if(down_interruptible(&dev->sem)) // TODO
return -ERESTARTSYS;
if(*f_pos > dev->size)
goto out;
if(*f_pos + count > dev->size)
count = dev->size - *f_pos;
// 查找listitem, qset index, and 量子中的偏移量
item = (long)*f_pos / itemsize;
rest = (long)*f_pos % itemsize;
s_pos = rest / quantum;
q_pos = rest % quantum;
// 遍歷list到右側(cè)
dptr = scull_follow(dev, item); // 量子集中的第一個(gè)元素
if(dptr == NULL || !dptr->data || !dptr->data[s_pos])
goto out;
// 只讀取到這個(gè)量子的尾部
if(count > quantum - q_pos)
count = quantum - q_pos;
if(copy_to_user(buf, dptr->data[s_pos] + q_pos, count)){
retval = -EFAULT;
goto out;
}
*f_pos += count;
retval = count;
out:
up(&dev->sem);
return retval;
}
// 一次處理單個(gè)量子
ssize_t scull_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos)
{
struct scull_dev *dev = filp->private_data;
struct scull_qset *dptr;
int quantum = dev->quantum, qset = dev->qset;
int itemsize = quantum * qset;
int item, s_pos, q_pos, rest;
ssize_t retval = -ENOMEM; // value used in "goto out" statements
if(down_interruptible(&dev->sem))
return -ERESTARTSYS;
// 查找列表元素,qset index and 量子中的偏移量
item = (long)*f_pos / itemsize;
rest = (long)*f_pos % itemsize;
s_pos = rest / quantum;
q_pos = rest % quantum;
// 遍歷list到右側(cè)
dptr = scull_follow(dev, item);
if(dptr == NULL):
goto out;
if(!dptr->data){
dptr->data = kmalloc(qset * sizeof(char), GPL_KERNEL);
if(!dptr->data)
goto out;
memset(dptr->data, 0, qset * sizeof(char *));
}
if(!dptr->data[s_pos]){
dptr->data[s_pos] = kmalloc(quantum, GFP_KERNEL);
if(!dptr->data[s_pos])
goto out;
}
// 只寫到這個(gè)量子的結(jié)束
if(count > quantum-q_pos)
count = quantum - q_pos;
// 從用戶空間拷貝一整段數(shù)據(jù)to from count
if(copy_from_user(dptr->data[s_pos]+q_pos, buf, count)){
retval = -EFAULT;
goto out;
}
*f_pos += count;
retval = count;
// 更新size
if(dev->size < *f_pos)
dev->size = *f_pos;
out:
up(&dev->sem);
return retval;
}
//-------------------------------
// read和write的"矢量"版本
// readv輪流讀取指示的數(shù)量到每個(gè)緩存;writev收集每個(gè)緩存的內(nèi)容到一起并且作為單個(gè)寫操作送出它們。
// count參數(shù)告訴有多少iovec結(jié)構(gòu),這些結(jié)構(gòu)由應(yīng)用程序創(chuàng)建,但是內(nèi)核在調(diào)用驅(qū)動(dòng)之前拷貝它們到內(nèi)核空間。
ssize_t (*readv)(struct file *filp, const struct iovec *iov, unsigned long count, loff_t *ppos);
ssize_t (*writev)(struct file *filp, const struct iovec *iov, unsigned long count, loff_t *ppos);
// iovec描述了一塊要傳送的數(shù)據(jù)
struct iovec{
void __user *iov_base; // 開始于iov_base(在用戶空間)
__kernel_size_t iov_len; // 并有iov_len長(zhǎng)
};
回復(fù) 更多評(píng)論 刪除評(píng)論 修改評(píng)論
# 重定向控制臺(tái)消息 2010-11-30 22:44 小默
// 重定向控制臺(tái)消息
// 使用一個(gè)參數(shù)指定接收消息的控制臺(tái)的編號(hào)
int main(int argc, char **argv)
{
char bytes[2] = {11, 0}; // 11 是 TIOCLINUX 的功能號(hào)
if(argc == 2) bytes[1] = atoi(argv[1]); // the chosen console
else{
fprintf(stderr, "%s: need a single arg\n", argv[0]);
exit(1);
}
// TIOCLINUX傳遞一個(gè)指向字節(jié)數(shù)組的指針作為參數(shù),數(shù)組的第一個(gè)字節(jié)是一個(gè)數(shù)(需要指定的子命令)。
// 當(dāng)子命令是11時(shí),下一個(gè)字節(jié)指定虛擬控制臺(tái)。
if(ioctl(STDIN_FILENO, TIOCLINUX, bytes)<0){ // use stdin
fprintf(stderr, "%s: ioctl(stdin, TIOCLINUX): %s\n", argv[0], stderror(errno));
exit(1);
}
exit(0);
}
回復(fù) 更多評(píng)論 刪除評(píng)論 修改評(píng)論
# Implementing files in /proc 2010-12-04 00:42 小默
// 在proc里實(shí)現(xiàn)文件,在文件被讀時(shí)產(chǎn)生數(shù)據(jù)。
// 當(dāng)一個(gè)進(jìn)程讀你的/proc文件,內(nèi)核分配了一頁內(nèi)存,驅(qū)動(dòng)可以寫入數(shù)據(jù)返回給用戶空間。
// buf 寫數(shù)據(jù)的緩沖區(qū);start有關(guān)數(shù)據(jù)寫在頁中哪里;eof必須被驅(qū)動(dòng)設(shè)置,表示寫數(shù)據(jù)結(jié)束;data用來傳遞私有數(shù)據(jù)。
// 假定不會(huì)有必要產(chǎn)生超過一頁的數(shù)據(jù),并且因此忽略了start和offset值。
int scull_read_procmem(char *buf, char **start, off_t offset, int count, int *eof, void *data)
{
int i, j, len = 0;
int limit = count - 80; // Don't print more than this
for(i = 0; i < scull_nr_devs && len <= limit; i++){ // TODO scull_nr_devs ?
struct scull_dev *d = &scull_devices[i];
struct scull_qset *qs = d->data;
if(down_interruptible(&d->sem))
return -ERESTARTSYS;
// 設(shè)備號(hào),量子集大小,量子大小,存儲(chǔ)的數(shù)據(jù)量
len += sprintf(buf+len, "\nDevice %i: qset %i, q %i, sz %li\n", i, d->qset, d->quantum, d->size);
for(; qs && len <= limit; qs = qs->next){ //scan the list 遍歷量子鏈表
// 元素地址、鏈表地址
len += sprintf(buf + len, " item at %p, qset at %p\n", qs, qs->data); // %p 顯示一個(gè)指針
if(qs->data && !qs->next) // dump only the last item
for(j = 0; j < d->qset, j++){
if(qs->data[j])
len += sprintf(buf+len, "%4i: %8p\n", j, qs->data[j]);
}
}
up(&scull_devices[i]);
}
*eof = 1;
return len; // 返回實(shí)際在頁中寫了多少數(shù)據(jù)
}
/// 移除entry的一些問題
// 移除可能發(fā)生在文件正在被使用時(shí)。/proc入口沒有owner,沒有引用計(jì)數(shù)。
// 內(nèi)核不檢查注冊(cè)的名字是否已經(jīng)存在,可能會(huì)有多個(gè)entry使用相同名稱。而且在訪問和remove_proc_entry時(shí),它們沒有區(qū)別。。。悲劇。。。 回復(fù) 更多評(píng)論 刪除評(píng)論 修改評(píng)論
# The seq_file interface 2010-12-04 10:56 小默
// 創(chuàng)建一個(gè)虛擬文件,遍歷一串?dāng)?shù)據(jù),這些數(shù)據(jù)必須返回用戶空間。
// start, next, stop, show
// sfile 總被忽略;pos指從哪兒開始讀,具體意義完全依賴于實(shí)現(xiàn)。
// seq_file典型的實(shí)現(xiàn)是遍歷一感興趣的數(shù)據(jù)序列,pos就用來指示序列中的下一個(gè)元素。
// 在scull中,pos簡(jiǎn)單地作為scull_array數(shù)組的索引。
// 原型
void *start(struct seq_file *sfile, loff_t *pos);
// 在scull中的實(shí)現(xiàn)
static void *scull_seq_start(struct seq_file *s, loff_t *pos)
{
if(*pos >= scull_nr_devs)
return NULL; // no more to read
return scull_devices + *pos; // 返回供迭代器使用的私有數(shù)據(jù)
}
// next把迭代器后挪一位,返回NULL表示沒有更多數(shù)據(jù)了
// v:上一次start/next調(diào)用返回的迭代器 TODO ???返回的不是私有數(shù)據(jù)么?
// pos: 文件中的當(dāng)前位置。
void *next(struct seq_file *sfile, void *v, loff_t *pos);
// scull的實(shí)現(xiàn)
static void *scull_seq_next(struct seq_file *s, void *v, loff_t *pos)
{
(*pos)++;
if(*pos >= scull_nr_devs)
return NULL;
return scull_devices + *pos;
}
// 內(nèi)核完成迭代器,調(diào)用stop清理
void stop(struct seq_file *sfile, void *v);
// scull沒有要清理的東西,stop方法是空的
// start到stop期間不會(huì)有sleep或者非原子操作,可以放心的在start中獲得信號(hào)量或自旋鎖。整個(gè)調(diào)用序列都是原子的。天書啊 TODO ???
// 在start和stop期間,內(nèi)核調(diào)用show輸出迭代器v生成的數(shù)據(jù)到用戶空間
int show(struct seq_file *sfile, void *v);
// 輸出,等效于用戶空間的printf。返回非0值表示緩沖滿,輸出的數(shù)據(jù)會(huì)被丟棄。不過大多數(shù)實(shí)現(xiàn)都忽略返回值。
int seq_sprintf(struct seq_file *sfile, const char *fmt, ...);
// 等效于用戶空間的putc和puts
int seq_putc(struct seq_file *sfile, char c);
int seq_puts(struct seq_file *sfile, const char *s);
// 如果s中有esc中的數(shù)據(jù),這些數(shù)據(jù)用8進(jìn)制輸出。常見的esc是"\t\n\\",用于保持空格,避免搞亂輸出。
int seq_escape(struct seq_file *m, const char *s, const char *esc);
// scull中show實(shí)現(xiàn)
static int scull_seq_show(struct seq_file *s, void *v)
{
struct scull_dev *dev = (struct scull_dev *)v;
struct scull_qset *d;
int i;
if(down_interrutible(&dev->sem))
return -ERESTARTSYS;
seq_printf(s, "\nDevice %i: qset %i, q %i, sz %li\n",
(int)(dev - scull_devices), dev->qset,
dev->quantum, dev->size);
for(d = dev->data; d; d = d->next){ // 遍歷鏈表
seq_printf(s, " item at %p, qset at %p\n", d, d->data);
if(d->data && !d->next) // dump only the last item
for(i = 0; i < dev->qset; i++){
if(d->data[i])
seq_printf(s, " %4i: %8p\n", i, d->data[i]);
}
}
up(&dev->sem);
return 0;
}
// 迭代器:指向scull_dev的一個(gè)指針,囧。。。
// 迭代器操作集
static struct seq_operations scull_seq_ops = {
.start = scull_seq_start,
.next = scull_seq_next,
.stop = scull_seq_stop,
.show = scull_seq_show
};
/// 用file_operations結(jié)構(gòu)結(jié)構(gòu),實(shí)現(xiàn)內(nèi)核read/seek文件的所有操作。
// 創(chuàng)建一個(gè)open方法,連接文件和seq_file操作 TODO 沒看懂
static int scull_proc_open(struct inode *inode, struct file *file)
{
// seq_open 連接文件和上面定義的scull_seq_ops
return seq_open(file, &scull_seq_ops);
}
// file_operations結(jié)構(gòu)
static struct fle_operations scull_proc_ops = {
.owner = THIS_MODULE,
.open = scull_proc_open,
.read = seq_read,
.llseek = seq_lseek,
.release = seq_release
};
// 在/proc中創(chuàng)建設(shè)備
entry = create_proc_entry("scullseq", 0, NULL);
if(entry)
entry->proc_fops = &scull_proc_ops;
// create_proc_entry原型
struct proc_dir_entry *create_proc_entry(const char *name,
mode_t, mode,
struct proc_dir_entry *parent); 回復(fù) 更多評(píng)論 刪除評(píng)論 修改評(píng)論
# strace命令 - debug 2010-12-04 14:12 小默
略 O(∩_∩)O~~ 回復(fù) 更多評(píng)論 刪除評(píng)論 修改評(píng)論
# ldd3_4.5_Debugging System Faults 2010-12-05 14:46 小默
講了兩部分
一、system opps
空指針引用,或者局部變量賦值覆蓋了原eip,導(dǎo)致頁錯(cuò)誤
二、系統(tǒng)掛起 // TODO 看得云里霧里的
死循環(huán)等引起
假掛起:鼠標(biāo)鍵盤等外設(shè)沒有響應(yīng)了,系統(tǒng)實(shí)際正常。可以看時(shí)間。。。
插入schedule調(diào)用防止死循環(huán),作用是允許其他進(jìn)程從當(dāng)前進(jìn)程竊取時(shí)間。講了些弊端,沒看懂
sysrq:沒看懂
回復(fù) 更多評(píng)論 刪除評(píng)論 修改評(píng)論
# re: 蓋樓 2010-12-26 06:13 小默
所謂原子操作,就是該操作絕不會(huì)在執(zhí)行完畢前被任何其他任務(wù)或事件打斷,也就說,它的最小的執(zhí)行單位,不可能有比它更小的執(zhí)行單位。
原子操作主要用于實(shí)現(xiàn)資源計(jì)數(shù),很多引用計(jì)數(shù)(refcnt)就是通過原子操作實(shí)現(xiàn)的。
原子類型定義:
typedef struct
{
volatile int counter;
}
atomic_t;
volatile修飾字段告訴gcc不要對(duì)該類型的數(shù)據(jù)做優(yōu)化處理,對(duì)它的訪問都是對(duì)內(nèi)存的訪問,而不是對(duì)寄存器的訪問。 回復(fù) 更多評(píng)論刪除評(píng)論 修改評(píng)論
# spinlock_t 2010-12-26 16:24 小默
17 typedef struct {
18 volatile unsigned int lock;
19 #ifdef CONFIG_DEBUG_SPINLOCK
20 unsigned magic;
21 #endif
22 } spinlock_t; 回復(fù) 更多評(píng)論 <a id="AjaxHolder_Comments_CommentList_ctl24_DeleteLink"