??xml version="1.0" encoding="utf-8" standalone="yes"?> 面的分配与回收使用了一个叫做buddy allocator的机Ӟkernelnewbies上的解释 mode׃n的内存的d权限Q和chmod的参数有点像。mode低九位定义了讉K许可Q解释如下:
主要用到open, close, read和writeq几个函敎ͼ关于它们的用方法可以?br />man 2 <函数?gt;
查看?br />
q里单介l下Q?br />Linux内核为每个进E维护了一张已打开的文件的表格Q用File DescriptorQ整型,以下写成fdQ可以访问到q些文g。所以很Ҏ理解tsh.c中的函数listjobsZ么需?br />一个output_fd的整型参敎ͼ注意它的后面有这么一行:
if (writer(output_fd, buf, strlen(buf)) < 0) ?br />
q一行就把前面构造好的buf字符Ԍ包括当前q程的信息)输出到这个output_fd对应的文件中了?br />
每个q程的gؓ0, 1, 2的fd都指向相同的文gQ?对应标准输入Q通常是键盘输入)Q?对应标准输出Q通常为屏q)Q?对应标准错误输出?br />
可以看到在mainҎ的开_有这么一?br /> dup2(1, 2);
dup2的作用是把参C指向的文件改成和参数一一P如果之前打开了文Ӟ则先关闭Q,q句话的作用是把原来要输出到标准错误端(stderr)的内?br />输出到标准输出端(stdout)Q便于调试?br />
理解了fd和dup2的作用后Q重定向也就很容易实CQ一U最单的Ҏ是先用open函数打开输出文gq得到对应的fdQ然后用dup2把标准输?输入端的指向Ҏ文g的fd
?br />
另外注意用open创徏输出重定向的文g的时候要加上S_IRUSR和S_IWUSR选项Q否则创建后的文件没有读写权限。(不过好像q个lab的测试数据比较厚道,会事先touch一下,不加q两个选项应该也能通过试Q?br />
一些文档中未定义的行ؓQ?br />argv
假如我输入的命o?bin/ls -l > ls.txtQ对应的argv应该包括哪些内容呢?
一般的情况argv的内容应该是['/bin/ls', '-l']Q后面的重定向符是不包括的不q在q个lab中似乎没有这个限Ӟ不去掉重定向和管道部分应该还是能通过试的?br />
Job ID的分?br />如果现在1, 2, 4号子d在后台运行,再新增一个进E的话应该给它分配多呢Q?br />q个问题不需要处理,只要所有的jobs队列操作l一使用tsh.c中给出的几个函数p?br />
其他Q?br />关于信号的{发、后台前台的转换{内容,文档和书上都说得很清楚了Q这里不再赘q?br />
P.S. 多进E程序的调试大家之前应该接触的比较少Q其实这个lab大致的代码不隑ֆQ难点在于细节上的debug比较困难Q调试过E对W八章的理解很有帮助?br />
]]>
使用vim xxx.cpp -V跟踪了打开的配|列表,发现有这么一D?br />
line 17: sourcing "/usr/share/vim/ftplugin/cpp.vim"
Searching for "ftplugin/c.vim ftplugin/c_*.vim ftplugin/c/*.vim" in "/home/wyx/.vim,/usr/share/vim,/usr/share/vim,
/usr/share/vim/after,/home/wyx/.vim/after"
Searching for "/home/wyx/.vim/ftplugin/c.vim"
line 12: sourcing "/home/wyx/.vim/ftplugin/c.vim"
原来/usr/share/vim/ftplugin/cpp.vim中直接调用了c.vim
runtime! ftplugin/c.vim ftplugin/c_*.vim ftplugin/c/*.vim
把这行注释掉Q问题解?img src ="http://m.tkk7.com/zellux/aggbug/193610.html" width = "1" height = "1" />
]]>
The memory allocation scheme used in the kernel. A vector of lists of free pages is kept, ordered by the size of the chunk (in powers of two). When a chunk is allocated, it is removed from the relevant list. When a chunk is freed back to the free pages pool, it is placed in the relevant list, starting from the top. If it is physically contiguous with a present chunk, they are merged and placed in the list above (i.e. where the chunks are twice the size), and this operation percolates up the vector. As regions are merged whenever possible, this design helps to reduce memory fragmentation.
首先在zone_struct{} 中保存了一个free_area_t数组Q这个数l记录了各种大小的空闲内存块的信息?br />include/linux/mmzone.h:
/**/
/*
* On machines where it is needed (eg PCs) we divide physical memory
* into multiple physical zones. On a PC we have 3 zones:
*
* ZONE_DMA < 16 MB ISA DMA capable memory
* ZONE_NORMAL 16-896 MB direct mapped by the kernel
* ZONE_HIGHMEM > 896 MB only page cache and user processes
*/
typedef
struct
zone_struct
{
/**/
/*
* Commonly accessed fields:
*/
spinlock_t
lock
;
unsigned
long
free_pages;
unsigned
long
pages_min, pages_low, pages_high;
int
need_balance;
/**/
/*
* free areas of different sizes
*/
//
数组中每个元素依ơ维?个pagesizeQ?个pagesizeQ?个pagesize……的I闲块的链表
free_area_t free_area[MAX_ORDER];
/**/
/*
* Discontig memory support fields.
*/
struct
pglist_data
*
zone_pgdat;
struct
page
*
zone_mem_map;
unsigned
long
zone_start_paddr;
unsigned
long
zone_start_mapnr;
/**/
/*
* rarely used fields:
*/
char
*
name;
unsigned
long
size;
}
zone_t;
free_area_struct {}typedef struct free_area_struct
{
struct list_head free_list;
unsigned long *map; // 某个特定大小的页面块分配情况的位?/span>
} free_area_t;
面分配Ӟ扑ֈ适合大小的free_area_struct{}Q然后从free_list中找有没有空闲的内存块,如果没有找更大的free_area_struct{}Q因为大都?^nQ很Ҏ把大块内存拆开Q一块分配给hQ剩下的保存到对应大的队列中?br />面回收时主要的问题是如何解册多的内存片。当面块被释放Ӟ先检查是否有相同大小的相ȝ闲块存在Q如果有的话q合v来(递归q程Q?img src ="http://m.tkk7.com/zellux/aggbug/182436.html" width = "1" height = "1" />
]]>
http://kerneltrap.org/Linux/Patching_CVE-2008-0600_Local_Root_Exploit
]]>
]]>
]]>
]]>
1. 2.4.20以后的内核出于安全考虑Q没有导出sys_call_tableW号Q所以要先通过System.map扑ֈsys_call_table的地址
$ cat /boot/System.map26 | grep sys_call_table
c0375680 R sys_call_table
另外也可以用nm工具获得vmlinux中的所有符?br />$ nm /usr/src/linux-2.6.24-ARCH/vmlinux | grep sys_call_table
l果一?br />
2. 以添加一个把uidҎroot(0)ZQ写一个内核模块:
addcall.c#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/unistd.h>
#include <linux/time.h>
#include <asm/uaccess.h>
#include <linux/sched.h>
#define __NR_changeuid 238
MODULE_DESCRIPTION("Change uid to 0");
MODULE_AUTHOR("ZelluX");
static int (*saved) (void);
void ** sys_call_table = 0xc0375680;
asmlinkage int sys_changeuid(void)
{
current->uid = current->euid = current->suid = current->fsuid = 0;
printk(KERN_ALERT "uid has been changed.");
return 0;
}
int __init init_addsyscall(void)
{
saved = (int (*) (void)) (sys_call_table[__NR_changeuid]);
sys_call_table[__NR_changeuid] = (unsigned long) sys_changeuid;
printk(KERN_ALERT "the call has been added.");
return 0;
}
void __exit exit_addsyscall(void)
{
sys_call_table[__NR_changeuid] = (unsigned long) saved;
printk(KERN_ALERT "the call has been removed");
}
module_init(init_addsyscall);
module_exit(exit_addsyscall);
对应的MakefileQ?br />ifneq ($(KERNELRELEASE),)
obj-m := addcall.o
else
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
default:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
endif
3. 使用insmod addcall.ko载入模块后,用dmesg可以看到the call has been added.
4. 试E序
test.c#include <linux/unistd.h>
#include <stdio.h>
#define __NR_changeuid 238
int main()
{
printf("Previous uid = %d\n", syscall(__NR_getuid));
syscall(__NR_changeuid);
printf("Current uid = %d\n", syscall(__NR_getuid));
return 0;
}
使用gcc -o test test.c~译
5. q行./testQ即可看到类似的成功信息Q?br />Previous uid = 1002
Current uid = 0
6. 卸蝲模块rmmod addcallQ此时再ơ运?/test׃p|
]]>#include <unistd.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#define KEY 1234
#define SIZE 1024
int main()
{
int shmid;
char *shmaddr;
struct shmid_ds buf;
shmid = shmget(KEY, SIZE, IPC_CREAT | 0600);
if (shmid == -1)
{
printf("Failed in creating shared memory: %s\n", strerror(errno));
return 0;
}
if (fork() == 0)
{
shmaddr = (char *) shmat(shmid, NULL, 0);
if (shmaddr == (void *) -1)
{
printf("Failed in connecting to the shared memory: %s\n", strerror(errno));
return 0;
}
strcpy(shmaddr, "Hello, this is child process!\n");
shmdt(shmaddr);
return 0;
} else
{
sleep(3);
shmctl(shmid, IPC_STAT, &buf);
printf("Size of the shared memory: ");
printf("shm_segsz = %d bytes\n", buf.shm_segsz);
printf("Process id of the creator: ");
printf("shm_cpid = %d\n", buf.shm_cpid);
printf("Process id of the last operator: ");
printf("shm_lpid = %d\n", buf.shm_lpid);
shmaddr = (char *) shmat(shmid, NULL, 0);
if (shmaddr == (void *) -1)
{
printf("Failed in connecting the shared memory: %s\n", strerror(errno));
return 0;
}
printf("The content of the shared memory: %s\n", shmaddr);
shmdt(shmaddr);
shmctl(shmid, IPC_RMID, NULL);
}
}
shmdt 取消一个进E的地址I间中的一块共享块的映?br />shmctl 理׃n内存Q和ioctl的风格很?br />
每一个新创徏的共享都׃个shmid_ds{}表示。struct shmid_ds在linux/shm.h中的定义Q?br />/**//* Obsolete, used only for backwards compatibility and libc5 compiles */
struct shmid_ds
{
struct ipc_perm shm_perm; /**//* operation perms */
int shm_segsz; /**//* size of segment (bytes) */
__kernel_time_t shm_atime; /**//* last attach time */
__kernel_time_t shm_dtime; /**//* last detach time */
__kernel_time_t shm_ctime; /**//* last change time */
__kernel_ipc_pid_t shm_cpid; /**//* pid of creator */
__kernel_ipc_pid_t shm_lpid; /**//* pid of last operator */
unsigned short shm_nattch; /**//* no. of current attaches */
unsigned short shm_unused; /**//* compatibility */
void *shm_unused2; /**//* ditto - used by DIPC */
void *shm_unused3; /**//* unused */
};
其中存放权限信息的ipc_perm{}的定义ؓQ?br />include/linux/ipc.h/**//* Obsolete, used only for backwards compatibility and libc5 compiles */
struct ipc_perm
{
__kernel_key_t key;
__kernel_uid_t uid;
__kernel_gid_t gid;
__kernel_uid_t cuid;
__kernel_gid_t cgid;
__kernel_mode_t mode;
unsigned short seq;
};
0400 用户可读 0200用户可写 0040 l成员可读?0020 l成员可写?0004 其他用户可读 0002 其他用户可写
没有执行?0100 0010 ?0001
]]>
最单的没有参数的系l调用的实现Q?br />/**//* XXX - _foo needs to be __foo, while __NR_bar could be _NR_bar. */
#define _syscall0(type,name) \
type name(void) \
{ \
long __res; \
__asm__ volatile ("int $0x80" \
: "=a" (__res) \
: "0" (__NR_##name)); \
__syscall_return(type,__res); \
}
int getuid(void)
{
long __res;
__asm__ volatile("int $0x80"
:"=a" (__res)
:"0" (__NR_getuid));
__syscall_return(int, __res);
}
arch/i386/kernel/traps.c中把该中断号l定到system_call函数Q?br />00944 set_system_gate(SYSCALL_VECTOR,&system_call);
system_call函数在arch/i386/kernel/entry.S中:ENTRY(system_call)
pushl %eax # save orig_eax
SAVE_ALL
GET_CURRENT(%ebx)
testb $0x02,tsk_ptrace(%ebx) # PT_TRACESYS
jne tracesys
cmpl $(NR_syscalls),%eax
jae badsys
call *SYMBOL_NAME(sys_call_table)(,%eax,4)
movl %eax,EAX(%esp) # save the return value
ENTRY(ret_from_sys_call)
cli # need_resched and signals atomic test
cmpl $0,need_resched(%ebx)
jne reschedule
cmpl $0,sigpending(%ebx)
jne signal_return
restore_all:
RESTORE_ALL
3. 得到当前task_struct的地址Q保存到ebx?br />4. 查系l调用号
5. Ҏ%eax调用可地址Q调用相应函?br />6. 在entry.S后面可以看到Q?br />.data
ENTRY(sys_call_table)
.long SYMBOL_NAME(sys_ni_syscall) /* 0 - old "setup()" system call*/
.long SYMBOL_NAME(sys_getuid16)
.long SYMBOL_NAME(sys_stime) /* 25 */
.long SYMBOL_NAME(sys_ptrace)
asmlinkage long sys_getuid16(void)
{
return high2lowuid(current->uid);
}
8. RESTORE_ALL
另外q里再提一下GET_CURRENT的实?br />#define GET_CURRENT(reg) \
movl $-8192, reg; \
andl %esp, reg
接下来是利用内核模块动态添加一个系l调用的例程Q由?.4.20以后sys_call_tableW号不再被导ZQ要获得q个地址得手动hack。尚未成功,下次回过头来看看?img src ="http://m.tkk7.com/zellux/aggbug/180462.html" width = "1" height = "1" />
]]>
]]>
作者:晏渭?
随着Linux2.6的发布,׃2.6内核做了新的改动Q各个设备的驱动E序在不同程度上要进行改写。ؓ了方便各位Linux爱好者我把自己整理的q分 文档share出来。该文当列D?.6内核同以前版本的l大多数变化Q可惜的是由于时间和_֊有限没有详细列出各个函数的用法?/p>
1?使用新的入口
必须包含 <linux/init.h>
module_init(your_init_func);
module_exit(your_exit_func);
老版本:int init_module(void);
void cleanup_module(voi);
2.4中两U都可以用,对如后面的入口函C必要昄包含M头文件?/p>
2?GPL
MODULE_LICENSE("Dual BSD/GPL");
老版本:MODULE_LICENSE("GPL");
3?模块参数
必须昑ּ包含<linux/moduleparam.h>
module_param(name, type, perm);
module_param_named(name, value, type, perm);
参数定义
module_param_string(name, string, len, perm);
module_param_array(name, type, num, perm);
老版本:MODULE_PARM(variable,type);
MODULE_PARM_DESC(variable,type);
4?模块别名
MODULE_ALIAS("alias-name");
q是新增的,在老版本中需?etc/modules.conf配置Q现在在代码中就可以实现?/p>
5?模块计数
int try_module_get(&module);
module_put();
老版本:MOD_INC_USE_COUNT ?MOD_DEC_USE_COUNT
http://www.fsl.cs.sunysb.edu/~sean/parser.cgi?modules
In 2.4 modules, the MOD_INC_USE_COUNT macro is used to prevent unloading of the module while there is an open file. The 2.6 kernel, however, knows not to unload a module that owns a character device that's currently open.
However, this requires that the module be explicit in specifying ownership of character devices, using the THIS_MODULE macro.
You also have to take out all calls to MOD_INC_USE_COUNT and MOD_DEC_USE_COUNT.
static struct file_operations fops =
{
.owner = THIS_MODULE,
.read = device_read,
.write = device_write,
.open = device_open,
.release = device_release
}
The 2.6 kernel considers modules that use the deprecated facility to be unsafe, and does not permit their unloading, even with rmmod -f.
2.6,2.5的kbuild不需要到处加上MOD_INC_USE_COUNT来消除模块卸载竞争(module unload raceQ?/p>
6?W号导出
只有昄的导出符h能被其他模块使用Q默认不导出所有的W号Q不必用EXPORT_NO_SYMBOLS
老板本:默认导出所有的W号Q除非用EXPORT_NO_SYMBOLS
7?内核版本?
需要在多个文g中包?lt;linux/module.h>Ӟ不必定义__NO_VERSION__
老版本:在多个文件中包含<linux/module.h>Ӟ除在L件外的其他文件中必须定义__NO_VERSION__Q防止版本重复定义?/p>
8?讑֤?
kdev_t被废除不可用Q新的dev_t拓展C32位,12位主讑֤P20位次讑֤受?
unsigned int iminor(struct inode *inode);
unsigned int imajor(struct inode *inode);
老版本:8位主讑֤P8位次讑֤?
int MAJOR(kdev_t dev);
int MINOR(kdev_t dev);
9?内存分配头文件变?
所有的内存分配函数包含在头文g<linux/slab.h>Q而原来的<linux/malloc.h>不存?
老版本:内存分配函数包含在头文g<linux/malloc.h>
10?l构体的初试?
gcc开始采用ANSI C的structl构体的初始化Ş式:
static struct some_structure = {
.field1 = value,
.field2 = value,
..
};
老版本:非标准的初试化Ş?
static struct some_structure = {
field1: value,
field2: value,
..
};
11?用户模式帮助?
int call_usermodehelper(char *path, char **argv, char **envp, int wait);
新增wait参数
12?request_module()
request_module("foo-device-%d", number);
老版本:
char module_name[32];
printf(module_name, "foo-device-%d", number);
request_module(module_name);
13?dev_t引发的字W设备的变化
1、取L讑֤号ؓ
unsigned iminor(struct inode *inode);
unsigned imajor(struct inode *inode);
2、老的register_chrdev()用法没变Q保持向后兼容,但不能访问设备号大于256的设备?
3、新的接口ؓ
a)注册字符讑֤范围
int register_chrdev_region(dev_t from, unsigned count, char *name);
b)动态申请主讑֤?
int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count, char *name);
看了q两个函数郁闷吧^_^Q怎么和file_operationsl构联系h啊?别急!
c)包含 <linux/cdev.h>Q利用struct cdev和file_operationsq接
struct cdev *cdev_alloc(void);
void cdev_init(struct cdev *cdev, struct file_operations *fops);
int cdev_add(struct cdev *cdev, dev_t dev, unsigned count);
Q分别ؓQ申请cdevl构Q和fopsq接Q将讑֤加入到系l中Q好复杂啊!Q?
d)void cdev_del(struct cdev *cdev);
只有在cdev_add执行成功才可q行?
e)辅助函数
kobject_put(&cdev->kobj);
struct kobject *cdev_get(struct cdev *cdev);
void cdev_put(struct cdev *cdev);
q一部分变化和新增的/sys/dev有一定的兌?/p>
14?新增?proc的访问操?
<linux/seq_file.h>
以前?proc中只能得到string, seq_file操作能得到如long{多U数据?
相关函数Q?
static struct seq_operations 必须实现q个cMfile_operations得数据中得各个成员函数?
seq_printf()Q?
int seq_putc(struct seq_file *m, char c);
int seq_puts(struct seq_file *m, const char *s);
int seq_escape(struct seq_file *m, const char *s, const char *esc);
int seq_path(struct seq_file *m, struct vfsmount *mnt,
struct dentry *dentry, char *esc);
seq_open(file, &ct_seq_ops);
{等
15?底层内存分配
1?lt;linux/malloc.h>头文件改?lt;linux/slab.h>
2、分配标志GFP_BUFFER被取消,取而代之的是GFP_NOIO ?GFP_NOFS
3、新增__GFP_REPEATQ__GFP_NOFAILQ__GFP_NORETRY分配标志
4、页面分配函数alloc_pages()Qget_free_page()被包含在<linux/gfp.h>?
5、对NUMApȝ新增了几个函敎ͼ
a) struct page *alloc_pages_node(int node_id, unsigned int gfp_mask, unsigned int order);
b) void free_hot_page(struct page *page);
c) void free_cold_page(struct page *page);
6?新增Memory pools
<linux/mempool.h>
mempool_t *mempool_create(int min_nr, mempool_alloc_t *alloc_fn, mempool_free_t *free_fn, void *pool_data);
void *mempool_alloc(mempool_t *pool, int gfp_mask);
void mempool_free(void *element, mempool_t *pool);
int mempool_resize(mempool_t *pool, int new_min_nr, int gfp_mask);
16?per-CPU变量
get_cpu_var();
put_cpu_var();
void *alloc_percpu(type);
void free_percpu(const void *);
per_cpu_ptr(void *ptr, int cpu)
get_cpu_ptr(ptr)
put_cpu_ptr(ptr)
老版本?
DEFINE_PER_CPU(type, name);
EXPORT_PER_CPU_SYMBOL(name);
EXPORT_PER_CPU_SYMBOL_GPL(name);
DECLARE_PER_CPU(type, name);
DEFINE_PER_CPU(int, mypcint);
2.6内核采用了可剥夺得调度方式这些宏都不安全?/p>
17?内核旉变化
1、现在的各个q_的HZ?
Alpha: 1024/1200; ARM: 100/128/200/1000; CRIS: 100; i386: 1000; IA-64: 1024; M68K: 100; M68K-nommu: 50-1000; MIPS: 100/128/1000; MIPS64: 100; PA-RISC: 100/1000; PowerPC32: 100; PowerPC64: 1000; S/390: 100; SPARC32: 100; SPARC64: 100; SuperH: 100/1000; UML: 100; v850: 24-100; x86-64: 1000.
2、由于HZ的变化,原来的jiffies计数器很快就溢出了,引入了新的计数器jiffies_64
3?include <linux/jiffies.h>
u64 my_time = get_jiffies_64();
4、新的时间结构增加了U秒成员变量
struct timespec current_kernel_time(void);
5、他的timer函数没变Q新?
void add_timer_on(struct timer_list *timer, int cpu);
6、新增纳U延时函数
ndelay()Q?
7、POSIX clocks 参考kernel/posix-timers.c
18?工作队列QworkqueueQ?
1、Q务队列(task queue Q接口函数都被取消,新增了workqueue接口函数
struct workqueue_struct *create_workqueue(const char *name);
DECLARE_WORK(name, void (*function)(void *), void *data);
INIT_WORK(struct work_struct *work,
void (*function)(void *), void *data);
PREPARE_WORK(struct work_struct *work,
void (*function)(void *), void *data);
2、申明struct work_structl构
int queue_work(struct workqueue_struct *queue, struct work_struct *work);
int queue_delayed_work(struct workqueue_struct *queue, struct work_struct *work,
unsigned long delay);
int cancel_delayed_work(struct work_struct *work);
void flush_workqueue(struct workqueue_struct *queue);
void destroy_workqueue(struct workqueue_struct *queue);
int schedule_work(struct work_struct *work);
int schedule_delayed_work(struct work_struct *work, unsigned long delay);
19?新增创徏VFS?libfs"
libfsl创Z个新的文件系l提供了大量的API.
主要是对struct file_system_type的实现?
参考源代码Q?
drivers/hotplug/pci_hotplug_core.c
drivers/usb/core/inode.c
drivers/oprofile/oprofilefs.c
fs/ramfs/inode.c
fs/nfsd/nfsctl.c (simple_fill_super() example)
20?DMA的变?
未变化的有:
void *pci_alloc_consistent(struct pci_dev *dev, size_t size, dma_addr_t *dma_handle);
void pci_free_consistent(struct pci_dev *dev, size_t size, void *cpu_addr, dma_addr_t dma_handle);
变化的有Q?
1?void *dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, int flag);
void dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, dma_addr_t dma_handle);
2、列举了映射方向Q?
enum dma_data_direction {
DMA_BIDIRECTIONAL = 0,
DMA_TO_DEVICE = 1,
DMA_FROM_DEVICE = 2,
DMA_NONE = 3,
};
3、单映射
dma_addr_t dma_map_single(struct device *dev, void *addr, size_t size, enum dma_data_direction direction);
void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, enum dma_data_direction direction);
4、页面映?
dma_addr_t dma_map_page(struct device *dev, struct page *page, unsigned long offset, size_t size, enum dma_data_direction direction);
void dma_unmap_page(struct device *dev, dma_addr_t dma_addr, size_t size, enum dma_data_direction direction);
5、有关scatter/gather的函敎ͼ
int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, enum dma_data_direction direction);
void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries, enum dma_data_direction direction);
6、非一致性映(Noncoherent DMA mappingsQ?
void *dma_alloc_noncoherent(struct device *dev, size_t size, dma_addr_t *dma_handle, int flag);
void dma_sync_single_range(struct device *dev, dma_addr_t dma_handle, unsigned long offset, size_t size,
enum dma_data_direction direction);
void dma_free_noncoherent(struct device *dev, size_t size, void *cpu_addr, dma_addr_t dma_handle);
7、DAC (double address cycle)
int pci_dac_set_dma_mask(struct pci_dev *dev, u64 mask);
void pci_dac_dma_sync_single(struct pci_dev *dev, dma64_addr_t dma_addr, size_t len, int direction);
21?互斥
新增seqlock主要用于Q?
1、少量的数据保护
2、数据比较简?没有指针)Qƈ且用频率很?
3、对不生Q何副作用的数据的讉K
4、访问时写者不被饿?
<linux/seqlock.h>
初始?
seqlock_t lock1 = SEQLOCK_UNLOCKED;
或seqlock_t lock2; seqlock_init(&lock2);
void write_seqlock(seqlock_t *sl);
void write_sequnlock(seqlock_t *sl);
int write_tryseqlock(seqlock_t *sl);
void write_seqlock_irqsave(seqlock_t *sl, long flags);
void write_sequnlock_irqrestore(seqlock_t *sl, long flags);
void write_seqlock_irq(seqlock_t *sl);
void write_sequnlock_irq(seqlock_t *sl);
void write_seqlock_bh(seqlock_t *sl);
void write_sequnlock_bh(seqlock_t *sl);
unsigned int read_seqbegin(seqlock_t *sl);
int read_seqretry(seqlock_t *sl, unsigned int iv);
unsigned int read_seqbegin_irqsave(seqlock_t *sl, long flags);
int read_seqretry_irqrestore(seqlock_t *sl, unsigned int iv, long flags);
22?内核可剥?
<linux/preempt.h>
preempt_disable()Q?
preempt_enable_no_resched()Q?
preempt_enable_noresched()Q?
preempt_check_resched()Q?/p>
23?眠和唤醒
1、原来的函数可用Q新增下列函敎ͼ
prepare_to_wait_exclusive()Q?
prepare_to_wait()Q?
2、等待队列的变化
typedef int (*wait_queue_func_t)(wait_queue_t *wait, unsigned mode, int sync);
void init_waitqueue_func_entry(wait_queue_t *queue, wait_queue_func_t func);
24?新增完成事gQcompletion eventsQ?
<linux/completion.h>
init_completion(&my_comp);
void wait_for_completion(struct completion *comp);
void complete(struct completion *comp);
void complete_all(struct completion *comp);
25?RCUQRead-copy-updateQ?
rcu_read_lock();
void call_rcu(struct rcu_head *head, void (*func)(void *arg),
void *arg);
26?中断处理
1、中断处理有q回g?
IRQ_RETVAL(handled)Q?
2、cli(), sti(), save_flags(), ?restore_flags()不再有效Q应该用local_save
_flags() 或local_irq_disable()?
3、synchronize_irq()函数有改?
4、新增int can_request_irq(unsigned int irq, unsigned long flags);
5?request_irq() 和free_irq() ?<linux/sched.h>改到?<linux/interrupt.h>
27?异步I/O(AIO)
<linux/aio.h>
ssize_t (*aio_read) (struct kiocb *iocb, char __user *buffer, size_t count, loff_t pos);
ssize_t (*aio_write) (struct kiocb *iocb, const char __user *buffer, size_t count, loff_t pos);
int (*aio_fsync) (struct kiocb *, int datasync);
新增Cfile_operationl构中?
is_sync_kiocb(struct kiocb *iocb)Q?
int aio_complete(struct kiocb *iocb, long res, long res2);
28?|络驱动
1、struct net_device *alloc_netdev(int sizeof_priv, const char *name, void (*setup)(struct net_device *));
struct net_device *alloc_etherdev(int sizeof_priv);
2、新增NAPI(New API)
void netif_rx_schedule(struct net_device *dev);
void netif_rx_complete(struct net_device *dev);
int netif_rx_ni(struct sk_buff *skb);
(老版本ؓnetif_rx())
29?USB驱动
老版本struct usb_driver取消了,新的l构体ؓ
struct usb_class_driver {
char *name;
struct file_operations *fops;
mode_t mode;
int minor_base;
};
int usb_submit_urb(struct urb *urb, int mem_flags);
int (*probe) (struct usb_interface *intf,
const struct usb_device_id *id);
30?block I/O ?
q一部分做的改动最大。不叙?/p>
31?mmap()
int remap_page_range(struct vm_area_struct *vma, unsigned long from, unsigned long to, unsigned long size, pgprot_t prot);
int io_remap_page_range(struct vm_area_struct *vma, unsigned long from, unsigned long to, unsigned long size, pgprot_t prot);
struct page *(*nopage)(struct vm_area_struct *area, unsigned long address, int *type);
int (*populate)(struct vm_area_struct *area, unsigned long address, unsigned long len, pgprot_t prot, unsigned long pgoff, int nonblock);
int install_page(struct mm_struct *mm, struct vm_area_struct *vma, unsigned long addr, struct page *page, pgprot_t prot);
struct page *vmalloc_to_page(void *address);
32?零拷贝块I/O(Zero-copy block I/O)
struct bio *bio_map_user(struct block_device *bdev, unsigned long uaddr, unsigned int len, int write_to_vm);
void bio_unmap_user(struct bio *bio, int write_to_vm);
int get_user_pages(struct task_struct *task, struct mm_struct *mm, unsigned long start, int len, int write, int force, struct page **pages, struct vm_area_struct **vmas);
33?高端内存操作kmaps
void *kmap_atomic(struct page *page, enum km_type type);
void kunmap_atomic(void *address, enum km_type type);
struct page *kmap_atomic_to_page(void *address);
老版本:kmap() ?kunmap()?/p>
34?驱动模型
主要用于讑֤理?
1?sysfs
2?Kobjects
推荐文章Q?
http:/www-900.ibm.com/developerWorks/cn/linux/kernel/l-kernel26/index.shtml
http:/www-900.ibm.com/developerWorks/cn/linux/l-inside/index.shtml
2.6里不需要再定义“__KERNEL__”?#8220;MODULE”了?
用下面的Makefile文g~译Q?/p>
代码:
obj-m := hello.o
KDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
default:
$(MAKE) -C $(KDIR) M=$(PWD) modules
我们在阅读linux源代码时都有q样的体?核心的组l相Ҏ散,在看一个文件时往往要牵涉到其他的头文g、源代码文g。如此来回蟩转寻扑֏量、常量、函数的定义十分不方便,q样折腾几次Q便使读代码的心情降C低点?br />
,比如我得到的是glimpse-4.12.5.tar.gz . 用rootdQ在M目录下用tar zxvf glimpse-4.12.5.tar.gz解开压羃包,在当前目录下出现新目录glimpse-4.12.5 . q入该目录,执行
./configure 如果单独使用glimpseQ那么只要简单的执行glimpseindex foo卛_Q其中foo是你惌索引的目录,比如说是/usr/src/linux .glimpseindex的执行结果是在你的v始目录下产生若干.glimpse*的烦引文件? 然后你只要执行glimpse yourstring卛_查找/usr/src/linux下所有包含字W串yourstring的文件? 对于lxrQ你可以讉Klxr.linux.no得到它的源代码解包后Q遵循如下步骤: 4)?INSTALLPREFIX/http/下增加一个文?htaccess内容Q?br />
<Files ~ (source|search|ident|diff|find)$> ***
lxr(linux cross reference)是一个解册个问题的工具Q?/strong>他对你指定的源代码文件徏立烦引数据库Q利用perl脚本CGI动态生成包含源码的web面Q你可以用Q何一U浏览器查阅。在此web中Q所有的变量、常量、函数都以超q接的Ş式给出,十分方便查阅。比如你在阅?usr/src/linux/net/socket.c的源代码Q发现函?get_empty_inode不知道是如何以及在哪里定义的Q这时候你只要点击get_empty_inode,lxr返回此函数的定义、实C及各ơ引用是在什么文件的哪一行,注意Q这些信息也是超q接Q点d直接跌{到相应的文g相应的行。另外lxrq提供标识符搜烦、文件搜索,l合E序 glimpseq可以提供对所有的源码文gq行全文索,甚至包括注释Q?br />
下面结合实例介l一下lxr和glimpse的基本安装和使用Q由于glimpse比较单,׃它开始:
首先讉K站点Q?http://glimpse.cs.arizona.edu/ 得到glimpse的源?/p>
make
make install
/*下面的文字来源于lxr的帮助文档以及本人的安装体会*/
1)修改Makefile中的变量PERLBIN和INSTALLPREFIX,使它们分别ؓ perlE序的位|和你想lxr安装的位|?在我的机器上QPERLBIN的gؓ/usr/bin/perl .至于INSTALLPREFIXQ有如下原则Qlxr的安装\径必Lweb服务器能有权限访问。因此它的值简单一点可?/home/httpd/html/lxr (对于Apache web server)?br />
2)执行 make install
3)修改$INSTALLPREFIX/http/lxr.conf :
baseurl : http://yourIP/lxr/http/
htmlhead: /home/httpd/html/lxr/http/template-head
htmltail: /home/httpd/html/lxr/http/template-tail
htmldir: /home/httpd/html/lxr/http/template-dir
sourceroot : /usr/src/linux # 假如对linux核心代码索引
dbdir : /home/httpd/html/lxr/dbdir/ #dbdirk可Q意v名,且位|Q?glimpsebin: /usr/bin/glimpse #可执行程序glimpse的位|?
SetHandler cgi-script
</Files>
5)按照lxr.conf中的讄建立dbdir ,按照上例,建立目录
/home/httpd/html/lxr/dbdir
q入q个目录执行$INSTALLPREFIX/bin/genxref yourdir
其中yourdir是源码目录,比如/usr/src/linux
如果要结合glimpseQ则执行glimpseindex -H . yourdir
6)修改 /etc/httpd/conf/httpd.conf ,加入
<Directory /home/httpd/html/lxr/http>
Options All
AllowOverride All
order allow,deny
allow from all
</Directory>
7)q入/etc/rc.d/init.d/ 执行
killall httpd
./httpd start
q入X Q用览?http://yourIP/lxr/http/blurb.html
大功告成 Q这下你可以舒心的读源码了?
]]>
3. 几个pacman常用的参?br />
pacman -Sy 更新本地包的数据?br />
pacman -S package_name1 package_name2 ... 安装?br />
pacman -S extra/package_name 指定安装某个版本的包
pacman -Su 更新所有安装的包,通常和Sy参数合ƈ?Syu
pacman -Ss 搜烦
pacman -U *.pkg.tar.gz 安装本地?/p>
4. 好不Ҏ+莫名奇妙地配好了昑֍Qstartx可以跑v来了
然后q行gnome-sessionQ提CGtk WARNING **: Cannot open display:
找了一堆解x法,ȝ有一个可行的Q?
在~/.xinitrc中增加gnome-sessionQ然后启动startx