一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

字符設(shè)備驅(qū)動程序 (1) - LDD3學(xué)習(xí)整理 - 小獸的窩

 yangshiquan 2011-04-25
字符設(shè)備驅(qū)動程序 (1)

#include <linux/module.h>
#include <linux/moduleparam.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/cdev.h>     /*cdev struct*/
#include <asm/system.h>     /*cli(),*_flags*/
#include <asm/uaccess.h> /*copy_ ....*/
#include "scull_t1.h" /*attention to the "" and <>*/

/*
*Our parameters which can be set at load time.
*
*/

int scull_major = SCULL_MAJOR;
int scull_minor = 0;
int scull_nr_devs = SCULL_NR_DEVS; /*number of bare scull devs*/
int scull_quantum = SCULL_QUANTUM; /*every one of quantum array has a quantum size*/
int scull_qset = SCULL_QSET;        /*the longth of quantum-set*/

module_param(scull_major,int,S_IRUGO);        /*knowledge 1*/
module_param(scull_monor,int,S_IRUGO);
module_param(scull_nr_devs,int,S_IRUGO);
module_param(scull_quantum,int,S_IRUGO);
module_param(scull_qset,int,S_IRUGO);

struct scull_dev *scull_devices; /*allocated in scull_init_module*/
/*
*Empty out (like "clean up")the scull device
*/

int scull_trim(struct scull_dev *dev) /*知識點(diǎn)4*/
{
    struct scull_qset *next,*dptr;
    int qset = dev->qset; /*amount of quantum*/
    int i;

    for(dptr = dev->data;dptr;dptr = next) /*循環(huán)scull_qset list 個數(shù)*/
    {
        if(dptr->data)
        {
            for(i = 0; i<qset; i++)
                kfree(dptr->data[i]); /*釋放dptr指向的數(shù)組的每個數(shù)組元素指向的quantum空間*/

            kfree(dptr->data);/* 釋放當(dāng)前的scull_set的量子集的空間*/
            dptr->data = NULL;/* 釋放一個scull_set中的void **data指針*/
            /*其實(shí)就我個人寫的話下面那句指向空會漏掉*/
        }
        next = dptr->next; /*下一個scull_qset list開始*/
        kfree(dptr); /*knowledge 2*/
    }
    dev->size =0; /*amount of data store here 為0*/
    dev->quantum = scull_quantum; /*set the quantum'size*//*你不是清空不,怎么還來設(shè)置它的大小啊*/
    dev->qset = scull_qset;         /*set the number of quantum in a array*//*同上的疑問*/
    dev->data = NULL;              /*釋放當(dāng)前的scull_device的struct scull_qset *data指針*/
    return 0;
}

/********************************************************************/
/*
*Open and close
*/

    
int scull_open(struct inode *inode,struct file *filp)
{
    struct scull_dev *dev; /*the information of this dev*/

    dev = contairner_of(inode->i_cdev,struct scull_dev, cdev); /*知識點(diǎn)3*/
    flip->private_data = dev; /*.將獲得的dev保存到filp->private_data*/
        /*如果是以只讀模式打開則調(diào)用scull_trim()截短設(shè)備為0*/
    if((filp->f_flags&O_ACCMODE) == O_WRONLY) /*這里注意是檢測打開的方式不是讀寫權(quán)限f_mode*/
    {
        if(down_interruptible(&dev->sem)) /* 對訪問區(qū)域加鎖*/
            return -ERESTARTSYS; /*猜想應(yīng)該是信號量不可用的意思吧??*/
        scull_trim(dev);
        up(&dev->sem);                        /* 解鎖*/
    }

}

int scull_release(struct inode *inode, struct file *filp)
{
    return 0;
    /*由于前面定義了scull是一個全局且持久的內(nèi)存區(qū),所以他的release什么都不做*/
}

/*
*Follow the list
*/

struct scull_qset *scull_follow(struct scull_dev *dev,int n)
{
    struct scull_qset *qs = dev->data;

    /*Allocate frist qset explicitly if need be*/
    if(! qs) /*當(dāng)list為null時*/
    {
        qs = dev->data = kmalloc(sizeof(struct scull_qset),GFP_KERNEL);
        if(qs == NULL)
            return NULL; /*??*/
        memset(qs,0,sizeof(struct scull_qset));    
    }
    /*follow the list*/
    while(n--)
    {
        if(!qs->next)
        {
            qs->next = kmalloc(sizeof(struct scull_qset), GFP_KERNEL);
            if (qs->next == NULL)
                return NULL; /* Never mind */
            memset(qs->next, 0, sizeof(struct scull_qset));
        }
        qs = qs->next;
        continue; /*這下我傻了*/
        return qs;
    }
}

/*
*read and write
*/


ssize_t scull_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
{
    struct scull_dev *dev = filp->private_data; /*獲得已經(jīng)保存在其中的設(shè)備結(jié)構(gòu)體入口指針*/
    struct scull_qset *dptr;                /*the first listitem*/
    int quantum = dev->quantum,qset = dev->qset;
    int itemsize = quantum *qset; /*這句很怪哦 不同的部分相互賦值干嗎啊??*/
    int item,s_pos,q_pos,rest;
    ssize_t retval = 0;

    if(down_interruptible(&dev->sem))
        return -ERESTARSYS;
    if(*f_pos >= dev->size) /*判讀off_t *f_pos參數(shù)是否超越了設(shè)備存儲的范圍*/
        goto out;
    if(*f_pos+count > dev->size)
        count = dev->size - *f_pos;

    /*find listitem,qset index,and offset in the quantum*//* 根據(jù)數(shù)組結(jié)構(gòu)得出相應(yīng)數(shù)據(jù) */
    item = (long)*f_pos/ itemsize; /*long???why???*/
    rest = (long)*f_pos%itemsize;
    s_pos = rest/quantum; /*no long ??why??*/
    q_pos = rest%quantum;

    /*follow the list up to the right position(defined elsewhere)*/
    dptr = scull_follow(dev,item);
    /*判斷各個數(shù)值的合法性并做修正*/
    if(dptr == NULL||!dptr->data||!dptr->data||!dptr->data[s_pos])
        goto out;
    /*read only up to the end of this quantum*/
    if(count>quantum - q_pos)
        count = quantum -q_pos;
    
    /*將內(nèi)核數(shù)據(jù)復(fù)制到用戶區(qū)域*/
    if(copy_to_user(buf, dptr->data[s_pos]+q_pos,count))/*發(fā)現(xiàn)自己對返回值還是不足*/
    {
        retval = -EFUALT;                                /*上面應(yīng)該是成功返回0非成功返回非0即真*/
        goto out;
    }    
    *f_pos += count;
    retval = count;
    
      out:
        up(&dev->sem);
        return retval;    
}

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; /*no mem used in "goto out"*/

    if(down_interruptible(&dev->sem))
        return -ERESTART;
    /*同read*/
    item = (long)*f_pos / itemsize;
    rest = (long)*f_pos % itemsize;

    s_pos = rest / quantum;
    q_pos = rest % quantum;    

    /* follow the list up to the right position */
    /*同read*/
    dptr = scull_follow(dev, item);    
        if (dptr == NULL)
        goto out;
    if (!dptr->data)
    {
        dptr->data = kmalloc(qset * sizeof(char *), GFP_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;
    }
    if (count > quantum - q_pos)
        count = quantum - q_pos;    
/*注意假如內(nèi)核訪問用戶區(qū)域,由于user域存在分頁機(jī)制,
進(jìn)程有可能被休眠以等待不再當(dāng)前頁中的數(shù)據(jù),所以需要
copy_from_user函數(shù)是可重入的.*/


    if(copy_from_user(dptr->data[s_pos]+q_pos, buf, count))
    {
        retval = -EFAULT; /*bad address*/
        goto out;    
    }
    *f_pos +=count;
    retval = count;
    /*updata the size*/
    /*實(shí)際上大多數(shù)情況讀寫函數(shù)是不能完全讀寫完的,所以做更新方便讀寫完的操作*/
    if(dev->size< *f_pos)
        dev->size = *f_pos;

    out:
        up(&dev->sem);
        return retval;
}

/*set file_operations*/
struct file_operations scull_fops =
{
    .owner = THIS_MODULE,
    .read = scull_read,
    .write = scull_write,
    .open = scull_open,
    .release = scull_release,
};

/*init and exit*/
void scull_cleanup_module(void)
{
    int i;
    dev_t devno = MKDEV(scull_major,scull_minor);/*獲取設(shè)備號*/

    /*get rid of dev entries*/
    if(scull_devices)
    {
        for(i = 0; i<scull_nr_devs; i++ )
        {
            scull_trim(scull_devices +i);
            cdev_del(&scull_devices[i].cdev);
        }
        kfree(scull_devices);
    }
    unregister_chrdev_region(devno, scull_nr_devs);
}

/*
*set up the char_dev structure for this device
*/

static void scull_setup_cdev(struct scull_dev *dev, int index)
{
    int err,devno = MKDEV(scull_major,scull_minor+index);
    /*初始化cdev,主要是指定其fops */
    cdev_init(&dev->cdev,&scull_fops); /*注冊設(shè)備結(jié)構(gòu)體*//*知識點(diǎn)5*/
    dev->cdev.owner = THIS_MODULE; /*注意這里是先注冊再初始化有些元素,原因有待查*/
    dev->cdev.ops = &scull_fops; /*cdev->init里面已經(jīng)初始化了 可省略*/
    err = cdev_add(&dev->cdev, devno,1) /*告知內(nèi)核該結(jié)構(gòu)體信息,設(shè)備注冊到這里才算真的激活*/
    if(err)
        printk(KERN_NOTICE "Error %d adding scull%d",err,index); /*這個失敗的可能很小書上這么提到why??*/    
}

int scull_init_module(void)
{
    int result,i;
    dev_t dev = 0;
    if (scull_major) /*選擇是否自動獲取設(shè)備號*/
    {
        dev = MKDEV(scull_major, scull_minor);
        result = register_chrdev_region(dev, scull_nr_devs, "scull");
    }
    else
    {
        result = alloc_chrdev_region(&dev, scull_minor, scull_nr_devs,
                "scull");
        scull_major = MAJOR(dev);
    }
    if (result < 0)
    {
        printk(KERN_WARNING "scull: can't get major %d\n", scull_major);
        return result;
    }
    /*
    *allocate the devices we can't have them static,as the number
    *can be specified at load time
    */

    scull_devices = kmalloc(scull_nr_devs*sizeof(struct scull_dev), GFP_KERNEL);/*分配nr個scull_dev的內(nèi)存*/
    if(!scull_devices)
    {
        result = -ENOMEM; /*NO enogh memory */
        goto fail;
    }
    memset(scull_devices,0,scull_nr_devs*sizeof(struct scull_dev)); /*kmalloc不清空*/

    /*init each device*/
    for(i = 0; i<scull_nr_devs;i++)
    {
        scull_devices[i].quantum = scull_quantum;
        scull_devices[i].qset = scull_qset;
        init_MUTEX(&scull_devices[i].sem); /*初始化旗幟變量 用于down_interruptible up(&xxx_dev->sem);*/
        scull_setup_cdev(&scull_devices[i],i); /*這個一定記得放于最后*/
    }
    return 0; /*succeed*/
    fail: /*知識點(diǎn)6 goto*/
        scull_cleanup_module();
        return result;
}

/*加載 注銷*/
module_init(scull_init_module);
module_exit(scull_cleanup_module);
/*程序信息*/
MODULE_AUTHOR("小獸");
MODULE_LICENSE("Dual BSD/GPL"); /*聽說不寫這個會有警告,等下編譯的時候試驗(yàn)下*/

 

 

/*knowledge 1 module_param
*我這樣理解這個函數(shù),它向當(dāng)前模塊傳入?yún)?shù)
*而這些參數(shù)是經(jīng)過該函數(shù)注冊的,帶有一定的屬性
*具體屬性可以跟蹤moduleparam.h里面的具體函數(shù),我想能
*理解好__attribute__這個家伙的性能應(yīng)該就能理解這個函數(shù)的意義了。
*值得注意的是,注冊數(shù)組之類的是用的別的類似于這個函數(shù)的函數(shù)
*
*這個知識點(diǎn)我犯錯了,因?yàn)楸旧鞮DD3上介紹得很清楚了,由于是很久以前看書
*時候看到的,給忘記了.... *應(yīng)該書它的作用是讓insmod命令對那些參數(shù)可見,而這
*種使用只是在調(diào)試的時候應(yīng)該
*用,至于平常視乎更多的是不允許這些參數(shù)被修改的。
*
*再次提醒自己,不要什么程序可以跑了基本能看懂就OK了,這樣的路遲早走不遠(yuǎn),更別說
*實(shí)現(xiàn)自己的理想。
****************************************************************************/

 

 

/*N0 2
* 關(guān)于指針釋放的,說實(shí)在的這里發(fā)現(xiàn)自己的C基礎(chǔ)很差,完全找不到
*指針釋放的概念,在這里做個筆記 提醒下以后多注意下
*/
/*NO3
*分配并填寫置于filp->private_data里的數(shù)據(jù)結(jié)構(gòu)。
*將初始化過的struct scull_dev dev的指針傳遞到filp->private_data里,以備后用
*
*具體說法為我們不需要cdev結(jié)構(gòu)體本身,但希望得到包含scull_dev結(jié)構(gòu)體?
*于是將scull_dev結(jié)構(gòu)體指針保存在private_data字段中,方便使用
*
*簡介點(diǎn)說是.通過indode->i_cdev(其本身指向scull_dev的cdev)獲得scull_dev的入口指針
*識別需要被打開的設(shè)備
*/

 

 

/***
*NO4
*
*scull_trim的實(shí)現(xiàn)相當(dāng)于遍歷了鏈表,先用dptr指針作為游標(biāo),指向每一個
*scull_qset,再通過量子集的大小dev->qset,在for循環(huán)中對dptr->data中的每一個量
*子進(jìn)行釋放。dptr->data是一個指針數(shù)組,所以kfree的參數(shù)為dptr->data[i]。把量
*子集釋放后再釋放dptr->data.接著通過next指針移動游標(biāo),再釋放當(dāng)前的dptr。
*完整的內(nèi)存釋放后再對scull_devices初始化。
*http://www./course/6_system/linux/Linuxjs/2008109/149527_2.html
*/

 

 

/*
*NO5 設(shè)備結(jié)構(gòu)體注冊詳情查看LDD3 P59
*記得剛接觸cdev這個家伙的時候是在跟著一本用老方法注冊設(shè)備的書做完兩個
*驅(qū)動之后的事了,為了接受這個結(jié)構(gòu)體花了不少時間,現(xiàn)在都不知道為什么,
*但確實(shí)卡了我好久。呵呵 想想好笑
*這里用戶自己定義的設(shè)備結(jié)構(gòu)體scull_dev中嵌入了cdev注意接受這種嵌入的方法!!!!
在open函數(shù)里面
* 通過indode->i_cdev(其本身指向scull_dev的cdev)獲得scull_dev的入口指針識別需要被打開的設(shè)備
* dev = container_of(inode->i_cdev, struct scull_dev, cdev);

* 將獲得的dev保存到filp->private_data filp->private_data = dev
*
這樣就完成了整個自己定義設(shè)備結(jié)構(gòu)體的嵌入工作
*/

 

 

/*
*NO6 goto
*大一接觸C的時候這個印象特深,說什么容易把程序跳亂不要亂用,前幾天看一些關(guān)于
*goto 的討論才知道,是個什么大師發(fā)表了一篇關(guān)于goto毒害的文章后才被認(rèn)為是毒瘤
*看了些資料后的整體認(rèn)識是:1:向后跳的話沒什么大礙,也不影響可讀性(短距離)
*                                    2:這里用到的錯誤恢復(fù)機(jī)制視乎沒有別的語句能比goto
*                                     更簡介的實(shí)現(xiàn)所需要的功能 這點(diǎn)蠻好的!
*                                    3:goto 源于匯編,可以說是比較底層的操作,很多破解直接
*                                     一個goto語句越過注冊碼算法部分 跳到檢測注冊碼后的
*                                     程序運(yùn)行部分破解就完成,所以你不能說它不強(qiáng)大!!!
*/

.h文件部分

 

#ifdef _SCULL_H_ /*這里沒懂 等下收集下頭文件書寫知識*/
#define _SCULL_H_

/*
*macros to help debugging
*/


#undef PDEBUG /*undef it, 怕別的地方定義了 會出錯,學(xué)習(xí)這個良好的習(xí)慣!!*/
#ifdef SCULL_DEBUG
/*
*下面這塊被注釋掉了 應(yīng)該是說要使用的時候再取消注釋吧 說到這里想到了
*#if 0 #endif 的強(qiáng)大了,通俗易懂 方便得很!!!
*在編譯時如果加上gcc -DSCULL_DEBUG即define SCULL_DEBUG
*/

# ifdef __KERNEL__
     /* This one if debugging is on, and kernel space */
# define PDEBUG(fmt, args...) printk( KERN_DEBUG "scull: " fmt, ## args)
# else
     /* This one for user space */
# define PDEBUG(fmt, args...) fprintf(stderr, fmt, ## args)
# endif
# else
# define PDEBUG(fmt, args...) /* not debugging: nothing */
# endif

#undef PDEBUGG
#define PDEBUGG(fmt, args...) /* nothing: it's a placeholder */ /*沒懂*/




#ifndef SCULL_MAJOR
#define SCULL_MAJOR 0 /*dynamic major by default*/
#endif
#ifndef SCULL_NR_DEVS
#define SCULL_NR_DEVS 4 /*scull0 through scull3*/
#endif
/*
*the bare device is a variable-length region of memory
*use a linked list of indirect blocks.
*scull_de->data points to an array pointers, each pointer refers to a memory area
*of SCULL_QUANTUM byte.
*
*The array quantum-set is SCULL_QSET long.
*
*/

#ifndef SCULL_QSET
#define SCULL_QSET 1000
#endif
#ifndef SCULL_QUANTUM
#define SCULL_QUANTUM 4000
#endif
/*
*Representation of scull quantum sets
*/

    //"scull_dev->data" points to an array of pointers, each

      //* pointer refers to a memory area of SCULL_QUANTUM bytes

struct scull_qset
{
    void **data;
    struct scull_qset *next;
};

struct scull_dev
{
    struct scull_qset *data; /*point to first quantum set*/
    int quantum;                /*size of quantum*/
    int qset; /*the current array size*/
    unsigned long size;        /*amount of data stored here*/
    unsigned int access_key; /*??*/
    struct semaphore sem;    /*mutual exclusion semaphore*/
    struct cdev cdev;            /*cdev.h*/
    
};
/*
 * The different configurable parameters
 *如果你寫個main函數(shù)要用到這些變量直接引用這個頭文件就OK啦 呵呵
 */

extern int scull_major; /* main.c */
extern int scull_nr_devs;
extern int scull_quantum;
extern int scull_qset;

/*
 * Prototypes for shared functions
 *以后就可以直接用咯 呵呵就是這個作用
 */



int scull_trim(struct scull_dev *dev);

ssize_t scull_read(struct file *filp, char __user *buf, size_t count,
                   loff_t *f_pos);
ssize_t scull_write(struct file *filp, const char __user *buf, size_t count,
                    loff_t *f_pos);


/*
 * Split minors in two parts
 *有待補(bǔ)充哦 這個還沒接觸下面的都還沒接觸 以后一定補(bǔ)上
 */

#define TYPE(minor)    (((minor) >> 4) & 0xf)    /* high nibble */
#define NUM(minor)    ((minor) & 0xf)        /* low nibble */

/*
 * Ioctl definitions
 */


/* Use 'k' as magic number */
#define SCULL_IOC_MAGIC 'k'
/* Please use a different 8-bit number in your code */

#define SCULL_IOCRESET _IO(SCULL_IOC_MAGIC, 0) reswords

/*
 * S means "Set" through a ptr,
 * T means "Tell" directly with the argument value
 * G means "Get": reply by setting through a pointer
 * Q means "Query": response is on the return value
 * X means "eXchange": switch G and S atomically
 * H means "sHift": switch T and Q atomically
 */

#define SCULL_IOCSQUANTUM _IOW(SCULL_IOC_MAGIC, 1, int)
#define SCULL_IOCSQSET _IOW(SCULL_IOC_MAGIC, 2, int)
#define SCULL_IOCTQUANTUM _IO(SCULL_IOC_MAGIC, 3)
#define SCULL_IOCTQSET _IO(SCULL_IOC_MAGIC, 4)
#define SCULL_IOCGQUANTUM _IOR(SCULL_IOC_MAGIC, 5, int)
#define SCULL_IOCGQSET _IOR(SCULL_IOC_MAGIC, 6, int)
#define SCULL_IOCQQUANTUM _IO(SCULL_IOC_MAGIC, 7)
#define SCULL_IOCQQSET _IO(SCULL_IOC_MAGIC, 8)
#define SCULL_IOCXQUANTUM _IOWR(SCULL_IOC_MAGIC, 9, int)
#define SCULL_IOCXQSET _IOWR(SCULL_IOC_MAGIC,10, int)
#define SCULL_IOCHQUANTUM _IO(SCULL_IOC_MAGIC, 11)
#define SCULL_IOCHQSET _IO(SCULL_IOC_MAGIC, 12)

/*
 * The other entities only have "Tell" and "Query", because they're
 * not printed in the book, and there's no need to have all six.
 * (The previous stuff was only there to show different ways to do it.
 */

#define SCULL_P_IOCTSIZE _IO(SCULL_IOC_MAGIC, 13)
#define SCULL_P_IOCQSIZE _IO(SCULL_IOC_MAGIC, 14)
/* ... more to come */

#define SCULL_IOC_MAXNR 14

#endif /* _SCULL_H_ */

makefile 部分

 

#內(nèi)核路徑
KERNELDIR = /home/alu/mywork/systems/linux-2.6.22.6

# $為取當(dāng)前變量 PWD為取當(dāng)前路徑
PWD := $(shell pwd)
#NO1 #N02
INSTALLDIR =/home/soso/ldd3/modules


CROSS_COMPLE =/usr/local/arm/crosstool/gcc-3.3.6-glibc-2.3.2/arm-linux/bin:
CC = $(CROSS_COMPLE)gcc

obj-m := scull.o
#NO3
#偽目標(biāo)1
modules:
    $(MAKE) -C $(KERNELDIR) M=$(PWD) modules
#N04

modules_install:
    cp scull.ko $(INSTALLDIR)
clean:
    rm -rf *.o *~core .depend .*.cmd *.ko *.mod.c .tmp_versions
.PHONY:modules modules_install clean
#NO5

 

 

###############################################################################
#NO1: :==的區(qū)別別
#:= 定義的變量如果值內(nèi)容本身就是變量,他不會延伸。如果是=:
#會延伸。所以在使用時,不需要延伸的時候一定要加上: ,防止不可
#控的情況。
#何為延伸:
#a = orginal_value
#b = $(a)
#a = later_value
#最后a=later_value
#和下面
#a = orginal_value
#b := $(a)
#a = later_value
#最后a=original_value
###############################################################################

###############################################################################
#NO2
#shell函數(shù)也不像其它的函數(shù)。顧名思義,它的參數(shù)應(yīng)該就是操作系統(tǒng)Shell的
#命令。它和反引號“`”是相同的功能。這就是說,shell函數(shù)把執(zhí)行操作系
#統(tǒng)命令后的輸出作為函數(shù)返回。于是,我們可以用操作系統(tǒng)命令以及字
#符串處理命令awk,sed等等命令來生成一個變量,如:
#contents := $(shell cat foo)
#files := $(shell echo *.c)
#注意,這個函數(shù)會新生成一個Shell程序來執(zhí)行命令,所以你要注意其運(yùn)行
#性能,如果你的Makefile中有一些比較復(fù)雜的規(guī)則,并大量使用了這個函數(shù),
#那么對于你的系統(tǒng)性能是有害的。特別是Makefile的隱晦的規(guī)則可能會讓你
#的shell函數(shù)執(zhí)行的次數(shù)比你想像的多得多。
#################################################################################

#################################################################################
#NO3
#值是y (for built-in)或者m(for module)。如果既不是y也不是m,這個文件不會被編譯
#或鏈接
#這里也是文件中的第一個目標(biāo)文件(target ) :<<who to write makefile>>中make是如何
#工作的 提到了這點(diǎn)
#我的理解是當(dāng)執(zhí)行make時 這條語句才是核心,他決定了最后所輸出的頂層
#最后發(fā)現(xiàn)這樣理解是錯誤的,因?yàn)闆]理解好modules這個偽目標(biāo)所指內(nèi)容的
#性能做完module分析后再聯(lián)系起來總結(jié)下。
#################################################################################

#################################################################################
#NO4 $(MAKE)
#四、嵌套執(zhí)行make
#在一些大的工程中,我們會把我們不同模塊或是不同功能的源文件放在
#不同的目錄中,我們可以在每個目錄中都書寫一個該目錄的Makefile,這有
#利于讓我們的Makefile變得更加地簡潔,而不至于把所有的東西全部寫在一
#個Makefile中,這樣會很難維護(hù)我們的Makefile,這個技術(shù)對于我們模塊編譯和
#分段編譯有著非常大的好處。
#例如,我們有一個子目錄叫subdir,這個目錄下有個Makefile文件,來指明了
#這個目錄下文件的編譯規(guī)則。那么我們總控的Makefile可以這樣書寫:
#subsystem:
#cd subdir && $(MAKE)
#其等價于:
#subsystem:
#$(MAKE) -C subdir
#定義$(MAKE)宏變量的意思是,也許我們的make需要一些參數(shù),所以定義成
#一個變量比較利于維護(hù)。這兩個例子的意思都是先進(jìn)入“subdir”目錄,然
#后執(zhí)行make命令。
#我們把這個Makefile叫做“總控Makefile”,總控Makefile的變量可以傳遞到下級的Makefile中
#(如果你顯示的聲明),但是不會覆蓋下層的Makefile中所定義的變量,除非指定
#了“-e”參數(shù)。
#摘自<<跟我一起寫 Makefile>>
#記起了以前學(xué)寫驅(qū)動的時候,我們的編譯過程是這樣的:在內(nèi)核(KERNELDIR)目錄的
#drivers/char的Makefile下增加obj-m += scull.o 在那個目錄下make modules就會在那個目錄下生成
#scull.ko文件然后移到開發(fā)板進(jìn)行加載卸載
#而在這里這個makefile相當(dāng)于遠(yuǎn)程控制(KERNELDIR)/Makefile 做出相同的操作即總控makefile
#######################################################################################

#######################################################################################
#NO5 .PHONY
#這個是偽目標(biāo)聲明標(biāo)志 具體知識請自己百度
###################################################################################

###################################################################################
#未解決知識點(diǎn)1:
#clean: 這個偽目標(biāo)具體跟的文件不怎么知道寫 我想可能要根據(jù)編譯過程最后生成的
#文件書寫 ,應(yīng)該是看最后都生成了些什么東西,然后寫上去。
#但都只是猜想,等下實(shí)踐后補(bǔ)上
###################################################################################

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多

    91精品视频免费播放| 国产免费操美女逼视频| 熟女中文字幕一区二区三区| 国产精品熟女乱色一区二区 | 日本午夜福利视频免费观看| 丰满少妇被粗大猛烈进出视频 | 国产色偷丝袜麻豆亚洲| 国产麻豆一线二线三线| 日韩在线免费看中文字幕| 午夜成年人黄片免费观看| 国产高清视频一区不卡| 麻豆在线观看一区二区| 狠狠做深爱婷婷久久综合| 好吊妞在线免费观看视频| 欧美特色特黄一级大黄片| 中文字幕亚洲精品人妻| 殴美女美女大码性淫生活在线播放| 国产亚州欧美一区二区| 日韩一区二区三区四区乱码视频| 一区二区三区日韩在线| 欧美午夜一级艳片免费看| 91日韩在线视频观看| 91精品视频免费播放| 午夜精品在线观看视频午夜| 五月天丁香婷婷狠狠爱| 久久免费精品拍拍一区二区| 免费黄色一区二区三区| 91插插插外国一区二区婷婷| 成人午夜激情免费在线| 日韩欧美三级视频在线| 亚洲精品高清国产一线久久| 日韩成人动画在线观看| 欧美日韩亚洲精品内裤| 欧美特色特黄一级大黄片| 五月婷婷综合缴情六月| 久久国产精品熟女一区二区三区 | 中国日韩一级黄色大片| 婷婷开心五月亚洲综合| 正在播放玩弄漂亮少妇高潮| 好吊日视频这里都是精品| 蜜桃传媒视频麻豆第一区|