⑴ linux下怎麼用c獲取硬碟物理序列號
1、在Linux系統中通過C語言獲取硬碟序列號,可以藉助於ioctl()函數,該函數原型如下:
intioctl(intfd,unsignedlongrequest,...);
ioctl的第一個參數是文件標識符,用open()函數打開設備時獲取。
ioctl第二個參數為用於獲得指定文件描述符的標志號,獲取硬碟序列號,一般指明為HDIO_GET_IDENTITY。
ioctl的第三個參數為一些輔助參數,要獲取硬碟序列號,需要藉助於structhd_driveid結構體來保存硬碟信息,該結構體在Linux/hdreg.h中,structhd_driveid的聲明如下
structhd_driveid{
unsignedshortconfig;/lotsofobsoletebitflags*/
unsignedshortcyls;/*Obsolete,"physical"cyls*/
unsignedshortreserved2;/*reserved(word2)*/
unsignedshortheads;/*Obsolete,"physical"heads*/
unsignedshorttrack_bytes;/*unformattedbytespertrack*/
unsignedshortsector_bytes;/*unformattedbytespersector*/
unsignedshortsectors;/*Obsolete,"physical"sectorspertrack*/
unsignedshortvendor0;/*vendorunique*/
unsignedshortvendor1;/*vendorunique*/
unsignedshortvendor2;/*Retiredvendorunique*/
unsignedcharserial_no[20];/*0=not_specified*/
unsignedshortbuf_type;/*Retired*/
unsignedshortbuf_size;/*Retired,512byteincrements
*0=not_specified
*/
……
};
2、源代碼如下
#include<stdio.h>
//ioctl()的聲明頭文件
#include<sys/ioctl.h>
//硬碟參數頭文件,hd_driveid結構聲明頭文件
#include<linux/hdreg.h>
//文件控制頭文件
#include<sys/fcntl.h>
intmain()
{
//用於保存系統返回的硬碟數據信息
structhd_driveidid;
//這里以第一塊硬碟為例,用戶可自行修改
//用open函數打開獲取文件標識符,類似於windows下的句柄
intfd=open("/dev/sda",O_RDONLY|O_NONBLOCK);
//失敗返回
if(fd<0){
perror("/dev/sda");
return1;}
//調用ioctl()
if(!ioctl(fd,HDIO_GET_IDENTITY,&id))
{
printf("SerialNumber=%s ",id.serial_no);
}
return0;
}
編譯完成後,執行效果如下:
⑵ ioctl()函數的參數和作用
因為用戶層定義它是個變參函數
ioctl (int __fd, unsigned long int __request, ...)
跟printf似的
⑶ 如何編寫Linux的驅動程序
}; //IO功能選項,硬體上拉輸出 static unsigned int gpio_cfg_table[] = { S3C2410_GPB5_OUTP, S3C2410_GPB6_OUTP, S3C2410_GPB7_OUTP, S3C2410_GPB8_OUTP, }; //編寫一個ioctl函數,這個函數提供給用戶端使用(也就是用戶態使用) static int my_ioctl(struct inode *inode,struct file* file,unsigned int cmd, unsigned long arg) { if (arg > 4) { return -EINVAL; } if (cmd == 1) //led ON { s3c2410_gpio_setpin(gpio_table[arg],0); return 0; } if (cmd == 0) //led OFF { s3c2410_gpio_setpin(gpio_table[arg],1); return 0; } else { return -EINVAL; } } //一個和文件設備相關的結構體。 static struct file_operations dev_fops = { .owner = THIS_MODULE, .ioctl = my_ioctl, //.read = my_read, //這個暫時屏蔽,一會我們再加入一個讀操作的函數 }; //linux中設備的注冊結構體 static struct miscdevice misc =
{ .minor = MISC_DYNAMIC_MINOR, .name = DEVICE_NAME, .fops = &dev_fops, }; //設備初始化(包括注冊)函數 static int __init dev_init(void) { int ret; int i; for (i=0;i<4;i++) { s3c2410_gpio_cfgpin(gpio_table[i],gpio_cfg_table[i]); s3c2410_gpio_setpin(gpio_table[i],0); mdelay(500); s3c2410_gpio_setpin(gpio_table[i],1); } ret = misc_register(&misc); printk(DEVICE_NAME"MY_LED_DRIVER init ok\n"); return ret; } //設備注銷函數 static void __exit dev_exit(void) { misc_deregister(&misc); } //與模塊相關的函數 mole_init(dev_init); mole_exit(dev_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("blog.ednchina.com/itspy");
MODULE_DESCRIPTION("MY LED DRIVER"); 到此,上面就完成了一個簡單的驅動(別急,下面我們再會稍微增加點復雜的東西),以上代碼的可以簡單概括為:像自己寫51單片機或者ARM的裸奔程序一樣操作IO函數,然後再linux系統中進行相關必須的函數關聯和注冊。 為什麼要關聯呢,為什麼注冊呢? 因為這是必須的,從以下這些結構體就知道了。 stuct file_operations{ struct mole *owner; loff_t (*llseek) (struct file *, loff_t, int); ssize_t (*read) (struct file *, char __user *, size_t, loff_t *); ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *); ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t); ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t); int (*readdir) (struct file *, void *, filldir_t);
unsigned int (*poll) (struct file *, struct poll_table_struct *); int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long); long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); … } file_operations 結構體中包括了很多與設備相關的函數指針,指向了驅動所提供的函數。 struct inode{ struct hlist_node i_hash; struct list_head i_list; struct list_head i_sb_list; struct list_head i_dentry; unsigned long i_ino; atomic_t i_count; unsigned int i_nlink; uid_t i_uid; gid_t i_gid; dev_t i_rdev; u64 i_version; loff_t i_size; … } inode 是 UNIX 操作系統中的一種數據結構,它包含了與文件系統中各個文件相關的一些重要信息。在 UNIX 中創建文件系統時,同時將會創建大量的 inode 。通常,文件系統磁碟空間中大約百分之一空間分配給了 inode 表。 大略了解以上信息之後,我們只需把我們所要實現的功能和結構體關聯起來。上例中已經完成IO寫操作的函數,現在我們再添加一個讀的函數。基於這種原理,我們想實現各種功能的驅動也就很簡單了。 //添加讀函數示意, 用戶層可以通過 read函數來操作。 static int my_read(struct file* fp, char __user *dat,size_t cnt) { size_t i; printk("now read the hardware...\n"); for(i=0;i<cnt;i++) dat[i] = 'A'; dat[i] = '\0'; return cnt; } 這樣,完成驅動編寫。編譯之後,本驅動可以通過直接嵌入內核中,也可以以模塊的嵌入的形式載入到linux內核中去。 完成了驅動,寫個應用程序了驗證一下吧: int main(int argc,char ** argv) {
int on; int led_no; int fd; char str[10]; int cnt =0; fd = open("/dev/MY_LED_DRIVER",0); if (fd < 0) { printf("can't open dev\n"); exit(1); } printf("read process\n"); cnt = read(fd,str,10); printf("get data from driver:\n%s\ncount = %d\n",str,cnt); printf("read process end \n"); cnt = 0; printf("running...\n"); while(cnt++<1000) { ioctl(fd,0,0); //led off ioctl(fd,0,1); ioctl(fd,0,2); ioctl(fd,0,3); sleep(1); //printf("sdfdsfdsfdsfds...\n"); ioctl(fd,1,0); //led on ioctl(fd,1,1); ioctl(fd,1,2); ioctl(fd,1,3); sleep(1); printf("%d\b",cnt); } close(fd); return 0; }
⑷ linux系統中的ioctl函數的CMD的幻數定義在哪裡定義是驅動程序中還是應用程序中
COMMAND命令字可以自己定義,也可以用不同驅動已定義的命令字。CMD命令字的用處打個比方,用戶層想使用內核層某驅動的一個功能,那麼它就可以通過IOCTL傳相應的命令字下去,給內核,內核通過接受到的命令字,實現相應功能。