1. 程式人生 > >《5.linux驅動開發-第3部分-5.3.字元裝置驅動高階》

《5.linux驅動開發-第3部分-5.3.字元裝置驅動高階》

《5.linux驅動開發-第3部分-5.3.字元裝置驅動高階》

第一部分、章節目錄
5.3.1.註冊字元裝置驅動新介面1
5.3.2.註冊字元裝置驅動新介面2
5.3.3.註冊字元裝置驅動新介面3
5.3.4.註冊字元裝置驅動新介面4
5.3.5.字元裝置驅動註冊程式碼分析1
5.3.6.字元裝置驅動註冊程式碼分析2
5.3.7.自動建立字元裝置驅動的裝置檔案
5.3.8.裝置類相關程式碼分析1
5.3.9.裝置類相關程式碼分析2
5.3.10.靜態對映表建立過程分析
5.3.11.動態對映結構體方式操作暫存器
5.3.12.核心提供的讀寫暫存器介面

第二部分、章節介紹
5.3.1.註冊字元裝置驅動新介面1
本節介紹核心中提供的字元裝置驅動註冊的新介面cdev,並且講了相關的介面函式,最後實踐編寫程式碼。
5.3.2.註冊字元裝置驅動新介面2
本節對上節講述的知識進行實踐程式設計測試。
5.3.3.註冊字元裝置驅動新介面3
本節講述新介面如何自動分配裝置號,以及其他一些程式設計細節如錯誤的逐級處理技巧。
5.3.4.註冊字元裝置驅動新介面4
本節講述cdev_alloc和cdev_init這兩個介面,同時引申講解了C語言如何以面向物件的程式設計方式來實現linux核心。
5.3.5.字元裝置驅動註冊程式碼分析1
本節帶大家瀏覽分析核心原始碼中與字元裝置驅動相關的介面,使用SourceInsight逐級追蹤的方式進入核心原始碼中。
5.3.6.字元裝置驅動註冊程式碼分析2
本節繼續上節分析字元裝置驅動註冊相關的介面函式,目的是教大家學習如何從原始碼中去學習。
5.3.7.自動建立字元裝置驅動的裝置檔案
本節實踐程式設計演示如何使用class_create和device_create這兩個介面來讓字元裝置驅動藉助裝置類自動建立及刪除裝置檔案。
5.3.8.裝置類相關程式碼分析1
本節開始分析class_create和device_create內部的實現原理。
5.3.9.裝置類相關程式碼分析2
本節接上節繼續分析,通過分析讓大家對sysfs有所瞭解,知曉核心如果通過sysfs和udev進行通訊以實現裝置檔案的自動建立和刪除。
5.3.10.靜態對映表建立過程分析
本節分析核心原始碼中與虛擬地址靜態對映建立有關的程式碼,通過分析大家可以進一步掌握靜態對映的實現細節。
5.3.11.動態對映結構體方式操作暫存器
本節對5.2.17中使用動態對映方式得到多個暫存器虛擬地址的程式碼進行改進,使用結構體封裝的方式讓我們能夠方便的對映多個暫存器。
5.3.12.核心提供的讀寫暫存器介面
本節介紹核心提供的writel/readl和iowrite32/ioread32等讀寫暫存器的介面,並且對之前的驅動進行改進,和核心中典型的驅動程式進行對比學習。

第三部分、隨堂記錄
5.3.1.註冊字元裝置驅動新介面1
5.3.1.1、新介面與老介面
(1)老介面:register_chrdev
(2)新介面:register_chrdev_region/alloc_chrdev_region + cdev
(3)為什麼需要新介面
5.3.1.2、cdev介紹
(1)結構體
(2)相關函式:cdev_alloc、cdev_init、cdev_add、cdev_del
5.3.1.3、裝置號
(1)主裝置號和次裝置號
(2)dev_t型別
(3)MKDEV、MAJOR、MINOR三個巨集
5.3.1.4、程式設計實踐
(1)使用register_chrdev_region + cdev_init + cdev_add進行字元裝置驅動註冊

#ubuntu的核心原始碼樹,如果要編譯在ubuntu中安裝的模組就開啟這2個
#KERN_VER = $(shell uname -r)
#KERN_DIR = /lib/modules/$(KERN_VER)/build	

		
# 開發板的linux核心的原始碼樹目錄
KERN_DIR = /root/driver/kernel

obj-m	+= module_test.o

all:
	make -C $(KERN_DIR) M=`pwd` modules 
	arm-linux-gcc app.c -o app

cp:
	cp *.ko /root/porting_x210/rootfs/rootfs/
driver_test cp app /root/porting_x210/rootfs/rootfs/driver_test .PHONY: clean clean: make -C $(KERN_DIR) M=`pwd` modules clean rm -rf app
#include <linux/module.h>		// module_init  module_exit
#include <linux/init.h>			// __init   __exit
#include <linux/fs.h>
#include <asm/uaccess.h>
#include <mach/regs-gpio.h>
#include <mach/gpio-bank.h>		// arch/arm/mach-s5pv210/include/mach/gpio-bank.h
#include <linux/string.h>
#include <linux/io.h>
#include <linux/ioport.h>
#include <linux/cdev.h>



#define MYMAJOR		200
#define MYCNT		1
#define MYNAME		"testchar"

#define GPJ0CON		S5PV210_GPJ0CON
#define GPJ0DAT		S5PV210_GPJ0DAT

#define rGPJ0CON	*((volatile unsigned int *)GPJ0CON)
#define rGPJ0DAT	*((volatile unsigned int *)GPJ0DAT)

#define GPJ0CON_PA	0xe0200240
#define GPJ0DAT_PA 	0xe0200244

unsigned int *pGPJ0CON;
unsigned int *pGPJ0DAT;

//**********************************************/
	int mymajor;
	static dev_t mydev;
	static struct cdev test_cdev;
//***********************************************/
char kbuf[100];			// 核心空間的buf


static int test_chrdev_open(struct inode *inode, struct file *file)
{
	// 這個函式中真正應該放置的是開啟這個裝置的硬體操作程式碼部分
	// 但是現在暫時我們寫不了這麼多,所以用一個printk列印個資訊來做代表。
	printk(KERN_INFO "test_chrdev_open\n");
	
	rGPJ0CON = 0x11111111;
	rGPJ0DAT = ((0<<3) | (0<<4) | (0<<5));		// 亮
	
	return 0;
}

static int test_chrdev_release(struct inode *inode, struct file *file)
{
	printk(KERN_INFO "test_chrdev_release\n");
	
	rGPJ0DAT = ((1<<3) | (1<<4) | (1<<5));
	
	return 0;
}

ssize_t test_chrdev_read(struct file *file, char __user *ubuf, size_t count, loff_t *ppos)
{
	int ret = -1;
	
	printk(KERN_INFO "test_chrdev_read\n");
	
	ret = copy_to_user(ubuf, kbuf, count);
	if (ret)
	{
		printk(KERN_ERR "copy_to_user fail\n");
		return -EINVAL;
	}
	printk(KERN_INFO "copy_to_user success..\n");
	
	
	return 0;
}

// 寫函式的本質就是將應用層傳遞過來的資料先複製到核心中,然後將之以正確的方式寫入硬體完成操作。
static ssize_t test_chrdev_write(struct file *file, const char __user *ubuf,
	size_t count, loff_t *ppos)
{
	int ret = -1;
	
	printk(KERN_INFO "test_chrdev_write\n");

	// 使用該函式將應用層傳過來的ubuf中的內容拷貝到驅動空間中的一個buf中
	//memcpy(kbuf, ubuf);		// 不行,因為2個不在一個地址空間中
	memset(kbuf, 0, sizeof(kbuf));
	ret = copy_from_user(kbuf, ubuf, count);
	if (ret)
	{
		printk(KERN_ERR "copy_from_user fail\n");
		return -EINVAL;
	}
	printk(KERN_INFO "copy_from_user success..\n");
	
	if (kbuf[0] == '1')
	{
		rGPJ0DAT = ((0<<3) | (0<<4) | (0<<5));
	}
	else if (kbuf[0] == '0')
	{
		rGPJ0DAT = ((1<<3) | (1<<4) | (1<<5));
	}	
	return 0;
}

//*****************************************************************************/
// 自定義一個file_operations結構體變數,並且去填充
static const struct file_operations test_fops = {
	.owner		= THIS_MODULE,				// 慣例,直接寫即可
	
	.open		= test_chrdev_open,			// 將來應用open開啟這個裝置時實際呼叫的
	.release	= test_chrdev_release,		// 就是這個.open對應的函式
	.write 		= test_chrdev_write,
	.read		= test_chrdev_read,
};
//*****************************************************************************/


static int __init chrdev_init(void)
{	
	int retval;
	printk(KERN_INFO "chrdev_init helloworld init\n");
	// 使用新的cdev介面來註冊字元裝置驅動
	// 新的介面註冊字元裝置驅動需要2步
//*****************************************************************************/	
*	// 第1步:註冊/分配主次裝置號
*	mydev = MKDEV(MYMAJOR, 0);
*	retval = register_chrdev_region(mydev, MYCNT, MYNAME);
*	if (retval) {
*		printk(KERN_ERR "Unable to register minors for %s\n", MYNAME);
*		return -EINVAL;
*	}
*	printk(KERN_INFO "register_chrdev_region success\n");
*	// 第2步:註冊字元裝置驅動
*	cdev_init(&test_cdev, &test_fops);
*	retval = cdev_add(&test_cdev, mydev, MYCNT);
*	if (retval) {
*		printk(KERN_ERR "Unable to cdev_add\n");
*		return -EINVAL;
*	}
*	printk(KERN_INFO "cdev_add success\n");
//*****************************************************************************/
	
	// 使用動態對映的方式來操作暫存器
	if (!request_mem_region(GPJ0CON_PA, 4, "GPJ0CON"))
		return -EINVAL;
	if (!request_mem_region(GPJ0DAT_PA, 4, "GPJ0CON"))
		return -EINVAL;
	
	pGPJ0CON = ioremap(GPJ0CON_PA, 4);
	pGPJ0DAT = ioremap(GPJ0DAT_PA, 4);
	
	*pGPJ0CON = 0x11111111;
	*pGPJ0DAT = ((0<<3) | (0<<4) | (0<<5));		// 亮
	

	return 0;
}

// 模組下載函式
static void __exit chrdev_exit(void)
{
	printk(KERN_INFO "chrdev_exit helloworld exit\n");

	*pGPJ0DAT = ((1<<3) | (1<<4) | (1<<5));	
	
	// 解除對映
	iounmap(pGPJ0CON);
	iounmap(pGPJ0DAT);
	release_mem_region(GPJ0CON_PA, 4);
	release_mem_region(GPJ0DAT_PA, 4);

/*	
	// 在module_exit巨集呼叫的函式中去登出字元裝置驅動
	unregister_chrdev(mymajor, MYNAME);
*/	
//*****************************************************************************/
	// 使用新的介面來登出字元裝置驅動
	// 登出分2步:
	// 第一步真正登出字元裝置驅動用cdev_del
	cdev_del(&test_cdev);
	// 第二步去登出申請的主次裝置號
	unregister_chrdev_region(mydev, MYCNT);
//*****************************************************************************/
}


module_init(chrdev_init);
module_exit(chrdev_exit);

// MODULE_xxx這種巨集作用是用來新增模組描述資訊
MODULE_LICENSE("GPL");				// 描述模組的許可證
MODULE_AUTHOR("aston");				// 描述模組的作者
MODULE_DESCRIPTION("module test");	// 描述模組的介紹資訊
MODULE_ALIAS("alias xxx");			// 描述模組的別名資訊
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>


#define FILE	"/dev/test"			// 剛才mknod建立的裝置檔名

char buf[100];

int main(void)
{
	int fd = -1;
	int i = 0;
	
	fd = open(FILE, O_RDWR);
	if (fd < 0)
	{
		printf("open %s error.\n", FILE);
		return -1;
	}
	printf("open %s success..\n", FILE);

/*	
	// 讀寫檔案
	write(fd, "on", 2);
	sleep(2);
	write(fd, "off", 3);
	sleep(2);
	write(fd, "on", 2);
	sleep(2);
*/
/*
	write(fd, "1", 1);
	sleep(2);
	write(fd, "0", 1);
	sleep(2);
	write(fd, "1", 1);
	sleep(2);
*/
	while (1)
	{
		memset(buf, 0 , sizeof(buf));
		printf("請輸入 on | off \n");
		scanf("%s", buf);
		if (!strcmp(buf, "on"))
		{
			write(fd, "1", 1);
		}
		else if (!strcmp(buf, "off"))
		{
			write(fd, "0", 1);
		}
		else if (!strcmp(buf, "flash"))
		{
			for (i=0; i<3; i++)
			{
				write(fd, "1", 1);
				sleep(1);
				write(fd, "0", 1);
				sleep(1);
			}
		}	
		else if (!strcmp(buf, "quit"))
		{
			break;
		}
	}

	
	// 關閉檔案
	close(fd);
	
	return 0;
}

5.3.2.註冊字元裝置驅動新介面2
5.3.2.1、實踐程式設計
5.3.2.2、測試

5.3.3.註冊字元裝置驅動新介面3
5.3.2.1、使用alloc_chrdev_region自動分配裝置號
(1)register_chrdev_region是在事先知道要使用的主、次裝置號時使用的;要先檢視cat /proc/devices去檢視沒有使用的。
(2)更簡便、更智慧的方法是讓核心給我們自動分配一個主裝置號,使用alloc_chrdev_region就可以自動分配了。
(3)自動分配的裝置號,我們必須去知道他的主次裝置號,否則後面沒法去mknod建立他對應的裝置檔案。
5.3.2.2、得到分配的主裝置號和次裝置號
(1)使用MAJOR巨集和MINOR巨集從dev_t得到major和minor
(2)反過來使用MKDEV巨集從major和minor得到dev_t。
(3)使用這些巨集的程式碼具有可移植性
5.3.2.3、中途出錯的倒影式錯誤處理方法
(1)核心中很多函式中包含了很多個操作,這些操作每一步都有可能出錯,而且出錯後後面的步驟就沒有進行下去的必要性了。

#ubuntu的核心原始碼樹,如果要編譯在ubuntu中安裝的模組就開啟這2個
#KERN_VER = $(shell uname -r)
#KERN_DIR = /lib/modules/$(KERN_VER)/build	

		
# 開發板的linux核心的原始碼樹目錄
KERN_DIR = /root/driver/kernel

obj-m	+= module_test.o

all:
	make -C $(KERN_DIR) M=`pwd` modules 
	arm-linux-gcc app.c -o app

cp:
	cp *.ko /root/porting_x210/rootfs/rootfs/driver_test
	cp app /root/porting_x210/rootfs/rootfs/driver_test
	

.PHONY: clean	
clean:
	make -C $(KERN_DIR) M=`pwd` modules clean
	rm -rf app

#include <linux/module.h>		// module_init  module_exit
#include <linux/init.h>			// __init   __exit
#include <linux/fs.h>
#include <asm/uaccess.h>
#include <mach/regs-gpio.h>
#include <mach/gpio-bank.h>		// arch/arm/mach-s5pv210/include/mach/gpio-bank.h
#include <linux/string.h>
#include <linux/io.h>
#include <linux/ioport.h>
#include <linux/cdev.h>



//#define MYMAJOR		200
#define MYCNT		1
#define MYNAME		"testchar"

#define GPJ0CON		S5PV210_GPJ0CON
#define GPJ0DAT		S5PV210_GPJ0DAT

#define rGPJ0CON	*((volatile unsigned int *)GPJ0CON)
#define rGPJ0DAT	*((volatile unsigned int *)GPJ0DAT)

#define GPJ0CON_PA	0xe0200240
#define GPJ0DAT_PA 	0xe0200244

unsigned int *pGPJ0CON;
unsigned int *pGPJ0DAT;


//int mymajor;
static dev_t mydev;
static struct cdev test_cdev;

char kbuf[100];			// 核心空間的buf


static int test_chrdev_open(struct inode *inode, struct file *file)
{
	// 這個函式中真正應該放置的是開啟這個裝置的硬體操作程式碼部分
	// 但是現在暫時我們寫不了這麼多,所以用一個printk列印個資訊來做代表。
	printk(KERN_INFO "test_chrdev_open\n");
	
	rGPJ0CON = 0x11111111;
	rGPJ0DAT = ((0<<3) | (0<<4) | (0<<5));		// 亮
	
	return 0;
}

static int test_chrdev_release(struct inode *inode, struct file *file)
{
	printk(KERN_INFO "test_chrdev_release\n");
	
	rGPJ0DAT = ((1<<3) | (1<<4) | (1<<5));
	
	return 0;
}

ssize_t test_chrdev_read(struct file *file, char __user *ubuf, size_t count, loff_t *ppos)
{
	int ret = -1;
	
	printk(KERN_INFO "test_chrdev_read\n");
	
	ret = copy_to_user(ubuf, kbuf, count);
	if (ret)
	{
		printk(KERN_ERR "copy_to_user fail\n");
		return -EINVAL;
	}
	printk(KERN_INFO "copy_to_user success..\n");
	
	
	return 0;
}

// 寫函式的本質就是將應用層傳遞過來的資料先複製到核心中,然後將之以正確的方式寫入硬體完成操作。
static ssize_t test_chrdev_write(struct file *file, const char __user *ubuf,
	size_t count, loff_t *ppos)
{
	int ret = -1;
	
	printk(KERN_INFO "test_chrdev_write\n");

	// 使用該函式將應用層傳過來的ubuf中的內容拷貝到驅動空間中的一個buf中
	//memcpy(kbuf, ubuf);		// 不行,因為2個不在一個地址空間中
	memset(kbuf, 0, sizeof(kbuf));
	ret = copy_from_user(kbuf, ubuf, count);
	if (ret)
	{
		printk(KERN_ERR "copy_from_user fail\n");
		return -EINVAL;
	}
	printk(KERN_INFO "copy_from_user success..\n");
	
	if (kbuf[0] == '1')
	{
		rGPJ0DAT = ((0<<3) | (0<<4) | (0<<5));
	}
	else if (kbuf[0] == '0')
	{
		rGPJ0DAT = ((1<<3) | (1<<4) | (1<<5));
	}
	
	
/*
	// 真正的驅動中,資料從應用層複製到驅動中後,我們就要根據這個資料
	// 去寫硬體完成硬體的操作。所以這下面就應該是操作硬體的程式碼
	if (!strcmp(kbuf, "on"))
	{
		rGPJ0DAT = ((0<<3) | (0<<4) | (0<<5));
	}
	else if (!strcmp(kbuf, "off"))
	{
		rGPJ0DAT = ((1<<3) | (1<<4) | (1<<5));
	}
*/

	
	
	return 0;
}


// 自定義一個file_operations結構體變數,並且去填充
static const struct file_operations test_fops = {
	.owner		= THIS_MODULE,				// 慣例,直接寫即可
	
	.open		= test_chrdev_open,			// 將來應用open開啟這個裝置時實際呼叫的
	.release	= test_chrdev_release,		// 就是這個.open對應的函式
	.write 		= test_chrdev_write,
	.read		= test_chrdev_read,
};



            
           

相關推薦

linux驅動開發-11部分-5.11.網路裝置驅動介紹》

《linux驅動開發-第11部分-5.11.網路裝置驅動介紹》 第一部分、章節目錄 5.11.1.網路裝置驅動概述 5.11.2.虛擬網絡卡驅動分析1 5.11.3.虛擬網絡卡驅動分析2 5.11.4.DM9000驅動原始碼分析1 5.11.5.DM9000驅動原始碼分析2 第二部分

5.linux驅動開發-10部分-5.10.塊裝置驅動介紹》

《5.linux驅動開發-第10部分-5.10.塊裝置驅動介紹》 第一部分、章節目錄 5.10.1.正確理解塊裝置驅動的概念 5.10.2.塊裝置驅動框架簡介 5.10.3.塊裝置驅動案例分析1 5.10.4.塊裝置驅動案例分析2 5.10.5.塊裝置驅動案例分析3 第二部分、章節介

5.linux驅動開發-7部分-5.7.framebuffer驅動詳解》

《5.linux驅動開發-第7部分-5.7.framebuffer驅動詳解》 第一部分、章節目錄 5.7.1.framebuffer介紹 5.7.2.framebuffer應用程式設計實踐1 5.7.3.framebuffer應用程式設計實踐2 5.7.4.framebuffer應用程式

5.linux驅動開發-6部分-5.6.misc類裝置與蜂鳴器驅動

《5.linux驅動開發-第6部分-5.6.misc類裝置與蜂鳴器驅動》 第一部分、章節目錄 5.6.1.板載蜂鳴器驅動測試 5.6.2.misc類裝置介紹 5.6.3.misc驅動框架原始碼分析1 5.6.4.misc驅動框架原始碼分析2 5.6.5.蜂鳴器驅動原始碼分析1 5.6.6

5.linux驅動開發-4部分-5.4.驅動框架入門之LED》

《5.linux驅動開發-第4部分-5.4.驅動框架入門之LED》 第一部分、章節目錄 5.4.1.何謂驅動框架 5.4.2.核心驅動框架中LED的基本情況 5.4.3.初步分析led驅動框架原始碼1 5.4.4.初步分析led驅動框架原始碼2 5.4.5.在核心中新增或去除某個驅動 5

5.linux驅動開發-2部分-5.2.字元裝置驅動基礎》

《5.linux驅動開發-第2部分-5.2.字元裝置驅動基礎》 第一部分、章節目錄 5.2.1.開啟驅動開發之路 5.2.2.最簡單的模組原始碼分析1 5.2.3.最簡單的模組原始碼分析2 5.2.4.最簡單的模組原始碼分析3 5.2.5.用開發板來除錯模組 5.2.6.字元裝置驅動工作

5.linux驅動開發-1部分-5.1.驅動應該怎麼學》

《5.linux驅動開發-第1部分-5.1.驅動應該怎麼學》 第一部分、章節目錄 5.1.1.什麼是驅動1 5.1.2.什麼是驅動2 5.1.3.模組化設計 5.1.4.linux裝置驅動分類 5.1.5.驅動程式的安全性要求 5.1.6.驅動應該這麼學 第二部分、章節介紹 5.1.

Linux裝置驅動程式學習(基於2440的GPIO字元裝置驅動)

GPIO驅動程式如下:  #include <linux/module.h> #include <linux/kernel.h> #include <linux/errno.h> #include <linux/string.h> #include <li

5.linux驅動開發-3部分-5.3.字元裝置驅動高階

《5.linux驅動開發-第3部分-5.3.字元裝置驅動高階》 第一部分、章節目錄 5.3.1.註冊字元裝置驅動新介面1 5.3.2.註冊字元裝置驅動新介面2 5.3.3.註冊字元裝置驅動新介面3 5.3.4.註冊字元裝置驅動新介面4 5.3.5.字元裝置驅動註冊程式碼分析1 5.3.6

5.linux驅動開發-5部分-5.8.input子系統基礎之按鍵》

《5.linux驅動開發-第5部分-5.8.input子系統基礎之按鍵》 第一部分、章節目錄 5.8.1.什麼是input子系統 5.8.2.input裝置應用層程式設計實踐1 5.8.3.input裝置應用層程式設計實踐2 5.8.4.input子系統架構總覽1 5.8.5.input

5.linux驅動開發-5部分-5.5.linux裝置驅動模型》

《5.linux驅動開發-第5部分-5.5.linux裝置驅動模型》 第一部分、章節目錄 5.5.1.linux裝置驅動模型簡介 5.5.2.裝置驅動模型的底層架構 5.5.3.匯流排式裝置驅動組織方式 5.5.4.platform平臺匯流排簡介1 5.5.5.platform平臺匯流排

求(3+開根5) N次方的整數部分最後3

\n using include none scan alt tdi typedef fine 求(3+開根5) N次方的整數部分最後3位,請補足前導零 。 分析:首先(1)=(3+開根5) N次方的展開為 an + bn * 根號5 的形式 。 同時也有 (2)=

linux操作指令 部分

groupdel 手動 左右 del cat pass useradd user 用戶操作 文件簡單操作 1.文件內容查看 > cat filename //一次性把全部內容都輸出到終端 > more filename

linux驅動開發(三) 字符設備驅動框架(自動創建設備節點)

The module __line__ mage fail goto div on() sys 代碼如下 #include <linux/init.h> #include <linux/module.h> #include <linux/ke

《2.uboot和系統移植-3部分-2.3.零距離初體驗uboot》

《2.uboot和系統移植-第3部分-2.3.零距離初體驗uboot》 第一部分、章節目錄 2.3.1_2.X210官方uboot配置編譯實踐 2.3.3.uboot的原始碼目錄分析1 2.3.4.uboot的原始碼目錄分析2 2.3.5.uboot的原始碼目錄分析3 2.3.6.Sou

遷移 Linux 系統, 1 部分 如何遷移備份和裸機恢復 Linux 系統

當硬體升級,更換儲存裝置或是遇到硬體故障時,需要遷移原來的作業系統及應用軟體到新的硬體裝置上。這個過程包含系統的遷移備份和裸機恢復,本文詳細描述了整個過程的細節。 災 難恢復 , 指自然或人為災害後,重新啟用資訊系統的資料、硬體及軟體裝置,恢復正常商業運作的過程。災難恢復是

ZYNQ Linux驅動開發——第一個字元裝置驅動

硬體平臺:XCZ7020 CLG484-1 完全適配Zedboard 開發環境:Widows下Vivado 2016.2 、 SDK2016.2 、 Linux機器:debin 目的:操作板載的LED燈LD9,受PS部分的MIO7控制 linux裝置驅

linux裝置驅動三篇:寫一個簡單的字元裝置驅動

在linux裝置驅動第一篇:裝置驅動程式簡介中簡單介紹了字元驅動,本篇簡單介紹如何寫一個簡單的字元裝置驅動。本篇借鑑LDD中的原始碼,實現一個與硬體裝置無關的字元裝置驅動,僅僅操作從核心中分配的一些記憶體。 下面就開始學習如何寫一個簡單的字元裝置驅動。首先我們來分解一下字元

linux驅動開發10之misc及蜂鳴器驅動

1.板載蜂鳴器驅動測試 1.1驅動部分 1)九鼎移植核心已經提供了蜂鳴器驅動原始碼 2)make menuconfig 3)bug排查。修改Makefile中的巨集名,最終可以在系統中看到 /dev/buzzer 由於makefile檔案與Kconfig檔案中的

從零開始寫linux字元裝置驅動程式(一)(基於友善之臂tiny4412開發板)

從這篇博文開始,我將開始手把手教會大家寫linux裝置驅動程式這是開篇,如何來寫第一個字元裝置驅動程式。首先,寫一個最簡單的字元裝置驅動程式需要什麼?或者說我們需要了解什麼?1、每一個字元裝置至少需要有一個裝置號2、裝置號 = 主裝置號 + 次裝置號3、同一類裝置的主裝置號一