linux內核讀寫
❶ linux kernel 怎麼讀cpu寫寄存器 inw
arm裸機下讀寫寄存器很容易,各個寄存器和內存的地址是單一地址空間,他們是用相同的指令進行讀寫操作的.而在linux下就要復雜很多,因為linux支持多個體系架構的CPU。比如arm和x86就不一樣,具體的差別我暫時也說不上來,這個涉及到CPU體系的設計。目前我只關心:linux為了支持多個硬體體系,在IO訪問上做了自己的介面。可以通過IO內存和IO埠這兩種方式進行IO訪問。在LED的例子上給出這兩種方式的具體實現:
1.利用IO Port的方式:
[cpp] view plain
#include <linux/mole.h>
#include <linux/moleparam.h>
#include <linux/init.h>
#include <linux/kernel.h> /* printk() */
#include <linux/slab.h> /* kmalloc() */
#include <linux/fs.h> /* everything... */
#include <linux/errno.h> /* error codes */
#include <linux/types.h> /* size_t */
#include <linux/proc_fs.h>
#include <linux/fcntl.h> /* O_ACCMODE */
#include <linux/seq_file.h>
#include <linux/cdev.h>
#include <linux/ioport.h>
#include <mach/regs-gpio.h>
#include <asm/system.h> /* cli(), *_flags */
#include <asm/uaccess.h> /* _*_user */
#include <asm/io.h>
#define LED_NUM 4
struct led_dev
{
struct cdev dev;
unsigned port;
unsigned long offset;
};
struct led_dev led[4];
dev_t dev = 0;
static struct resource *led_resource;
int led_open(struct inode *inode, struct file *filp)
{
struct led_dev *led; /* device information */
led = container_of(inode->i_cdev, struct led_dev, dev);
filp->private_data = led; /* for other methods */
return 0; /* success */
}
int led_release(struct inode *inode, struct file *filp)
{
return 0;
}
ssize_t led_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
{
return 0;
}
ssize_t led_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos)
{
char data;
struct led_dev *led;
u32 value;
printk(KERN_INFO "debug by kal: led dev write\n");
led = (struct led_dev *)filp->private_data;
_from_user(&data,buf,count);
if(data == '0')
{
printk(KERN_INFO "debug by kal: led off\n");
value = inl((unsigned)(S3C2410_GPBDAT));
outl(value | 1<<led->offset,(unsigned)(S3C2410_GPBDAT));
//value = ioread32(led->base);
//iowrite32( value | 1<<led->offset, led->base);
}
else
{
printk(KERN_INFO "debug by kal: led on\n");
value = inl((unsigned)(S3C2410_GPBDAT));
outl(value & ~(1<<led->offset),(unsigned)(S3C2410_GPBDAT));
//value = ioread32(led->base);
//iowrite32( value & ~(1<<led->offset), led->base);
}
}
struct file_operations led_fops = {
.owner = THIS_MODULE,
.read = led_read,
.write = led_write,
//.ioctl = led_ioctl,
.open = led_open,
.release = led_release,
};
static int led_init(void)
{
int result, i;
result = alloc_chrdev_region(&dev, 0, LED_NUM,"LED");
if (result < 0) {
printk(KERN_WARNING "LED: can't get major %d\n", MAJOR(dev));
return result;
}
led_resource = request_region(0x56000014,0x4,"led");
if(led_resource == NULL)
{
printk(KERN_ERR " Unable to register LED I/O addresses\n");
return -1;
}
for(i = 0; i < LED_NUM; i++)
{
cdev_init( &led[i].dev, &led_fops);
//led[i].port = ioport_map(0x56000014,0x4);
//led[i].base = ioremap(0x56000014,0x4);
led[i].offset = i + 5; //leds GPB5\6\7\8
led[i].dev.owner = THIS_MODULE;
led[i].dev.ops = &led_fops;
result = cdev_add(&led[i].dev,MKDEV(MAJOR(dev),i),1);
if(result < 0)
{
printk(KERN_ERR "LED: can't add led%d\n",i);
return result;
}
}
return 0;
}
static void led_exit(void)
{
int i;
release_region(0x56000014,0x4);
for( i = 0; i < LED_NUM; i++)
{
//iounmap(led[i].base);
cdev_del(&led[i].dev);
}
unregister_chrdev_region(dev, LED_NUM);
}
mole_init(led_init);
mole_exit(led_exit);
MODULE_AUTHOR("Baikal");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Simple LED Driver");
2.利用IO Mem的方式:
[cpp] view plain
#include <linux/mole.h>
#include <linux/moleparam.h>
#include <linux/init.h>
#include <linux/kernel.h> /* printk() */
#include <linux/slab.h> /* kmalloc() */
#include <linux/fs.h> /* everything... */
#include <linux/errno.h> /* error codes */
#include <linux/types.h> /* size_t */
#include <linux/proc_fs.h>
#include <linux/fcntl.h> /* O_ACCMODE */
#include <linux/seq_file.h>
#include <linux/cdev.h>
#include <linux/ioport.h>
#include <asm/system.h> /* cli(), *_flags */
#include <asm/uaccess.h> /* _*_user */
#include <asm/io.h>
#define LED_NUM 4
struct led_dev
{
struct cdev dev;
void __iomem *base;
unsigned long offset;
};
struct led_dev led[4];
dev_t dev = 0;
int led_open(struct inode *inode, struct file *filp)
{
struct led_dev *led; /* device information */
led = container_of(inode->i_cdev, struct led_dev, dev);
filp->private_data = led; /* for other methods */
return 0; /* success */
}
int led_release(struct inode *inode, struct file *filp)
{
return 0;
}
ssize_t led_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
{
return 0;
}
ssize_t led_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos)
{
char data;
struct led_dev *led;
u32 value;
printk(KERN_INFO "debug by kal: led dev write\n");
led = (struct led_dev *)filp->private_data;
_from_user(&data,buf,count);
if(data == '0')
{
printk(KERN_INFO "debug by kal: led off\n");
value = ioread32(led->base);
iowrite32( value | 1<<led->offset, led->base);
}
else
{
printk(KERN_INFO "debug by kal: led on\n");
value = ioread32(led->base);
iowrite32( value & ~(1<<led->offset), led->base);
}
}
struct file_operations led_fops = {
.owner = THIS_MODULE,
.read = led_read,
.write = led_write,
//.ioctl = led_ioctl,
.open = led_open,
.release = led_release,
};
static int led_init(void)
{
int result, i;
result = alloc_chrdev_region(&dev, 0, LED_NUM,"LED");
if (result < 0) {
printk(KERN_WARNING "LED: can't get major %d\n", MAJOR(dev));
return result;
}
for(i = 0; i < LED_NUM; i++)
{
cdev_init( &led[i].dev, &led_fops);
request_mem_region(0x56000014,0x4,"led");
led[i].base = ioremap(0x56000014,0x4);
led[i].offset = i + 5; //leds GPB5\6\7\8
led[i].dev.owner = THIS_MODULE;
led[i].dev.ops = &led_fops;
result = cdev_add(&led[i].dev,MKDEV(MAJOR(dev),i),1);
if(result < 0)
{
printk(KERN_ERR "LED: can't add led%d\n",i);
return result;
}
}
return 0;
}
static void led_exit(void)
{
int i;
release_mem_region(0x56000014,0x4);
for( i = 0; i < LED_NUM; i++)
{
iounmap(led[i].base);
cdev_del(&led[i].dev);
}
unregister_chrdev_region(dev, LED_NUM);
}
mole_init(led_init);
mole_exit(led_exit);
MODULE_AUTHOR("Baikal");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Simple LED Driver");
❷ linux內核閱讀方法
獲取內核
一般在Linux系統中的/usr/src/linux*.*.*(*.*.*代表的是內核版本,如2.4.23)目錄下就是內核原始 碼(如果沒有類似目錄,是因為還沒安裝內核代碼)。另外還可從互連網上免費下載。注意,不要總到http://www.kernel.org/去下載,最 佳使用他的映像站點下載。請在http://www.kernel.org/mirrors/里找一個合適的下載點,再到pub/linux /kernel/v2.6/目錄下去下載2.4.23內核。這里有兩種類型的代碼包,即linux-2.4.23.tar.gz和linux- 2.4.23.tar.bz2。兩個代碼包內容是相同的,只是壓縮程式不同。.gz是用gzip壓縮的;.bz2是用bzip2壓縮的。bzip2的壓縮 能力比gzip強。
代碼目錄結構
在閱讀源碼之前,還應知道Linux內核源碼的整體分布情況。現代的操作系統一般由進程管理、內存管理、文件系統、驅動程式和網路等組成。Linux內核源碼的各個目錄大致和此相對應,其組成如下(假設相對於Linux-2.4.23目錄):
◆arch目錄包括了所有和體系結構相關的核心代碼。他下面的每一個子目錄都代表一種Linux支持的體系結構,例如i386就是Intel CPU及和之相兼容體系結構的子目錄。PC機一般都基於此目錄。
◆include目錄包括編譯核心所需要的大部分頭文件,例如和平台無關的頭文件在include/linux子目錄下。
◆init目錄包含核心的初始化代碼(不是系統的引導代碼),有main.c和Version.c兩個文件。這是研究核心怎麼工作的好起點。
◆mm目錄包含了所有的內存管理代碼。和具體硬體體系結構相關的內存管理代碼位於archkernel目錄下。
◆net目錄里是核心的網路部分代碼,其每個子目錄對應於網路的一個方面。
◆lib目錄包含了核心的庫代碼,不過和處理器結構相關的庫代碼被放在arch/*/lib/目錄下。
◆scripts目錄包含用於設置核心的腳本文件。
◆documentation目錄下是一些文件,是對每個目錄作用的具體說明。
一 般在每個目錄下都有一個.depend文件和一個Makefile文件。這兩個文件都是編譯時使用的輔助文件。仔細閱讀這兩個文件對弄清各個文件之間的聯 系和依託關系非常有幫助。另外有的目錄下更有Readme文件,他是對該目錄下文件的一些說明,同樣有利於對內核源碼的理解。
閱讀起步
在 閱讀方法或順序上,有縱向和橫向之分。所謂縱向就是順著程式的執行順序逐步進行;所謂橫向,就是按模塊進行。他們經常結合在一起進行。對於Linux啟動 的代碼可順著Linux的啟動順序一步步來閱讀;對於像內存管理部分,能獨立拿出來進行閱讀分析。實際上這是個反復的過程,不可能讀一遍就理解。
LXR(http://lxr.linux.no) 是個輔助閱讀的好工具,他能對指定的源碼文件建立索引資料庫,利用Perl腳本動態生成包含源碼的Web頁面。在此Web頁中,所有的變數、常量和函數都 以超連接的形式給出,查閱十分方便。另外,LXR還提供標識符搜索和文件搜索,結合程式 Glimpse(http://glimpse.cs.arizona.e)還能對所有的源碼文件進行全文檢索,甚至包括注釋。其安裝方法能參照其代 碼中的幫助文件。在Window下也有一適合Linux內核閱讀的工具稱作Source Insight(可從http://www.sourcedyn.com下載)。
❸ 怎樣讀Linux內核源代碼
在閱讀源碼之前,還應知道Linux內核源碼的整體分布情況。現代的操作系統一般由進程管理、內存管理、文件系統、驅動程序和網路等組成。Linux內核源碼的各個目錄大致與此相對應,其組成如下(假設相對於Linux-2.4.23目錄):
1.arch目錄包括了所有和體系結構相關的核心代碼。它下面的每一個子目錄都代表一種Linux支持的體系結構,例如i386就是Intel CPU及與之相兼容體系結構的子目錄。PC機一般都基於此目錄。
2.include目錄包括編譯核心所需要的大部分頭文件,例如與平台無關的頭文件在include/linux子目錄下。
3.init目錄包含核心的初始化代碼(不是系統的引導代碼),有main.c和Version.c兩個文件。這是研究核心如何工作的好起點。
4.mm目錄包含了所有的內存管理代碼。與具體硬體體系結構相關的內存管理代碼位於arch/*/mm目錄下。
5.drivers目錄中是系統中所有的設備驅動程序。它又進一步劃分成幾類設備驅動,每一種有對應的子目錄,如音效卡的驅動對應於drivers/sound。
6.ipc目錄包含了核心進程間的通信代碼。
7.moles目錄存放了已建好的、可動態載入的模塊。
8.fs目錄存放Linux支持的文件系統代碼。不同的文件系統有不同的子目錄對應,如ext3文件系統對應的就是ext3子目錄。
Kernel內核管理的核心代碼放在這里。同時與處理器結構相關代碼都放在arch/*/kernel目錄下。
9.net目錄里是核心的網路部分代碼,其每個子目錄對應於網路的一個方面。
10.lib目錄包含了核心的庫代碼,不過與處理器結構相關的庫代碼被放在arch/*/lib/目錄下。
11.scripts目錄包含用於配置核心的腳本文件。
12.documentation目錄下是一些文檔,是對每個目錄作用的具體說明。
一般在每個目錄下都有一個.depend文件和一個Makefile文件。這兩個文件都是編譯時使用的輔助文件。仔細閱讀這兩個文件對弄清各個文件之間的聯系和依託關系很有幫助。另外有的目錄下還有Readme文件,它是對該目錄下文件的一些說明,同樣有利於對內核源碼的理解。
在閱讀方法或順序上,有縱向與橫向之分。所謂縱向就是順著程序的執行順序逐步進行;所謂橫向,就是按模塊進行。它們經常結合在一起進行。對於Linux啟動的代碼可順著Linux的啟動順序一步步來閱讀;對於像內存管理部分,可以單獨拿出來進行閱讀分析。實際上這是一個反復的過程,不可能讀一遍就理解。
❹ linux 內核怎麼讀寫磁碟扇區
linux下可以使用hdparm命令查看硬碟的信息。 你可以在C語言裡面,調用hdparm,並獲取其輸出信息即可。 也可以查找hdparm程序的源代碼,把查找序列號的代碼加進來。
❺ 如何在linux內核中讀寫文件
首先保證系統有linux內核源碼 下載內核源碼,版本可以更改 1> sudo apt-get install linux-source-2.6.35 下載內核源碼一般在/usr/src目錄中 2>進入/usr/src中解壓內核源碼 3>然後執行cd /usr/src/內核目錄
❻ 我想在linux的內核模塊中對文件進行打開讀寫等操作,可以實現嗎
內核模塊linux源代碼聯系些概念我都模糊linux系統由各種各內核模塊組
實驗源代碼:
//my_proc.c
#include<linux/mole.h>
#include<linux/kernel.h>
#include<linux/proc_fs.h>
#include<linux/sched.h>
#include<linux.uaccess.h>
#define STRINGLEN 1024
char global_buffer[STRINGLEN];
struct proc_dir_entry *example_dir,*Tang_file,*Yang_file,*symlink;
int proc_read_Tang(char *page,char **start,off_t off,int count,int *eof,void *data)
{//用戶讀取Tang文件內核調用函數
int len;
try_mole_get(THIS_MODULE);//模塊引用計數器
len=printf(page,"Tang message:\nname: %s\npid: %d\n",current->comm,current->pid);
mole_put(THISMODULE);
return len;
}
int proc_read_Yang(char *page,char **start,off_t off,int count,int *eof,void *data)
{//用戶讀取Yu文件內核調用函數
int len;
try_mole_get(THIS_MODULE);
len=printf(page,"Yang message:\n%s write: %s\n",current->comm,global_buffer);
mole_put(THISMODULE);
return len;
}
int proc_write_Yang(struct file *file, const char *buffer, unsigned long count, void *data)
{//用戶讀寫數據入Yang文件內核調用函數
int len;
try_mole_get(THIS_MODULE);
if(count>=STRINGLEN)
len=STRINGLEN-1;
else
len=count;
_from_user(global_buffer,buffer,len);
global_buffer[len]='\0';
mole_put(THISMODULE);
return len;
}
int init_mole()
{//初始化函數
example_dir=proc_mkdir("13081175",NULL);
example_dir->owner=THIS_MODULE;
Tang_file=create_proc_read_entry("Tang",0444,example_dir,proc_rea d_current,NULL);
Tang_file->read_proc=proc_read_Tang;
Tang_file->owner=THIS_MODULE;
Yang_file=create_proc_entry("Yang",0666,example);
strcpy(global_buffer,"Tang");
Yang_file->read_proc=proc_read_Yang;
Yang_file->write_proc=proc_write_Yang;
Yang_file->owner=THIS_MOUDLE;
return 0;
}
void cleanup_mole()
{//卸載函數
remove_proc_entry("Yang",example_dir);
remove_proc_entry("Tang",example_dir);
remove_proc_entry("21",NULL);
}
編寫Makefile文件內容:
obj-m := my_proc.o
KERNELBUILD :=/lib/moles/$(shell uname -r)/build
default:
make -C $(KERNELBUILD) M=$(shell pwd) moles
clean:
rm -rf *.o *.ko *.mod.c .*.cmd *.markers *.order *.symvers .tmp_versions
❼ 如何在linux內核模塊中對串口進行讀寫 100flycofei
多用戶系統,除了系統資源有爭搶以外,2個用戶的操作不會互相影響操作界面,有字元界面,也有圖形界面。linux的圖形界面和系統關系不大,只是一個應用程序,圖形界面有很多種,每個人都可以定製自己的linux文件系統,和圖形界面一樣,跟linux.