亚洲av成人无遮挡网站在线观看,少妇性bbb搡bbb爽爽爽,亚洲av日韩精品久久久久久,兔费看少妇性l交大片免费,无码少妇一区二区三区

  免費注冊 查看新帖 |

Chinaunix

  平臺 論壇 博客 文庫
最近訪問板塊 發(fā)新帖
查看: 2549 | 回復(fù): 9
打印 上一主題 下一主題

新人求助:一個塊設(shè)備是否可以同時對多個bio進(jìn)行處理 [復(fù)制鏈接]

論壇徽章:
0
跳轉(zhuǎn)到指定樓層
1 [收藏(0)] [報告]
發(fā)表于 2008-12-23 16:25 |只看該作者 |倒序瀏覽
牛人幫忙哈。。

最近在做一個類似ramdisk的塊設(shè)備驅(qū)動,想要在驅(qū)動中實現(xiàn)多線程的訪問。但在測試中發(fā)現(xiàn),每次進(jìn)入驅(qū)動讀寫的都只有一個線程,所有有上面的疑問。

     驅(qū)動結(jié)構(gòu)類似于ramdisk的不使用隊列的形式

     首先申請請求隊列
     mcard_queue=blk_alloc_queue(GFP_KERNEL);

     注冊處理請求隊列的函數(shù) self_make_request
     blk_queue_make_request(mcard_queue,&self_make_request);


     在self_make_request()中直接處理bio,完成從內(nèi)存到設(shè)備的 數(shù)據(jù)傳輸
     static int self_make_request(request_queue_t *mcard_queue, struct bio * bio)
    {
        …………
        bio_for_each_segment(bvec,bio,i)
        {       
                dbg_assert_print("%d times transfer, current sector is %llu\n", i, sector);
                char * addr = bio_to_phys(bio);   //物理地址
                pcie_enter_dma++;
                mcard_transfer(sector, rw, bio, addr);    //具體的傳輸,類似ramdisk的memcpy()
                sector += bio_cur_sectors(bio);
        }
        bio_endio(bio,bio->bi_size,0);
        return 0;
    }

     自己想當(dāng)然的情況:在多個進(jìn)程使用設(shè)備進(jìn)行讀寫的時候, 每個 進(jìn)程都會通過generic_make_request()函數(shù),進(jìn)入self_make_request()來處理io請求--bio。

     測試結(jié)果:在多個進(jìn)程使用設(shè)備進(jìn)行讀寫的時候,都只有 一個 進(jìn)程能進(jìn)入self_make_request();不知道是什么原因。

參看了ldd3 和understanding linux 的相關(guān)章節(jié),還是摸不著頭腦。

猜測是在上層的submit_bio( ) ,generic_make_request( )相關(guān)處理中加了鎖,每次限制只能處理一個bio。但看了代碼沒發(fā)現(xiàn)鎖。

論壇徽章:
3
金牛座
日期:2014-06-14 22:04:062015年辭舊歲徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:49:45
2 [報告]
發(fā)表于 2008-12-23 16:35 |只看該作者
你把整個驅(qū)動的代碼都列出來吧,應(yīng)該是底層的互斥機(jī)制導(dǎo)致不能并發(fā)訪問的

論壇徽章:
0
3 [報告]
發(fā)表于 2008-12-23 17:53 |只看該作者

回復(fù) #2 dreamice 的帖子

:wink:
整個的太長,大都是寄存器和初始化的一些操作,主要的處理函數(shù)就3個:
mcard_make_request
mcard_interrupt
mcard_transfer

mcard_make_request 調(diào)用 mcard_transfer 來進(jìn)行具體的傳輸
mcard_interrupt 通過中斷來喚醒mcard_make_request繼續(xù)下面的操作

/*********************************************************************
* transfer:   mcard_transfer
* handle the DMA ops
*/

void mcard_transfer(unsigned long sector, int rw, struct bio *bio, unsigned long long * addr)
{

        unsigned long long local_addr;
        unsigned long byte_count;
       
        local_addr = sector * 512;          //當(dāng)前處理的設(shè)備內(nèi)存的偏移
        byte_count = bio_iovec(bio)->bv_len;
        switch(rw){
                case READA:
                case READ:
                        dma_read_flag = 0;
                        MCARD_START_DMA_WRITE(addr, local_addr, byte_count);
                        wait_event_interruptible(mcard_read_queue, dma_read_flag == 1));
                        break;

                case WRITE:
                        dma_write_flag = 0;
                        MCARD_START_DMA_READ(addr, local_addr, byte_count);
                        wait_event_interruptible(mcard_write_queue, dma_write_flag == 1);
                        break;
                default:
                        printk("ERROR: blk cmd error!!!.\n";
                        break;
        }
}

/*********************************************************************
* make_request:   mcard__make_request
*make request function
*/
static int mcard_make_request(request_queue_t *mcard_que, struct bio * bio)
{
        int i, rw;
        sector_t sector;
        unsigned long len;
        struct bio_vec *bvec;

        sector = bio->bi_sector;         //bio起始的sector
        rw = bio_data_dir(bio);
       
        bio_for_each_segment(bvec,bio,i)
        {       
                char * addr = bio_to_phys(bio);   //物理地址
                mcard_transfer(sector, rw, bio, addr);
                sector += bio_cur_sectors(bio);
        }
        bio_endio(bio,bio->bi_size,0);
        return 0;
}

/*********************************************************************
* mcard_interrupt
*/
static irqreturn_t mcard_interrupt(int irq, void *data, struct pt_regs *regs)
{
        unsigned int interrupt_flag;
        interrupt_flag = MEMORY_MAPPED_IO_32BIT(MCARD_INTERRUPT_STATUS);
        smp_mb();
        if(!(interrupt_flag))
                return IRQ_NONE;
        MEMORY_MAPPED_IO_32BIT(MCARD_INTERRUPT_CLEAR)= interrupt_flag;//0xFFFFFFFF;
        smp_wmb();        

        switch (tmp_interrupt_flag )
        {
                case DMA_READ_SUCCESS_FLAG :  //DMA READ -- sys_wtire
                        dma_write_flag = 1;               
                        smp_mb();
                        wake_up_interruptible(&mcard_write_queue);
                        break;

                case DMA_WRITE_SUCCESS_FLAG :
                        dma_read_flag = 1;               
                        smp_mb();
                        wake_up_interruptible(&mcard_read_queue);
                        break;

                case TIMEOUT_WRITE_FLAG:
                        panic("time out for write occurred\n";
                        break;
                case TIMEOUT_READ_FLAG:
                        panic("time out for read occurred\n";
                        break;
                default:
                        printk("INTERRUPT ERROR,flag error, val is %d\n", interrupt_flag);
                        break;

        }
        return IRQ_HANDLED;
}

[ 本帖最后由 taylergreen 于 2008-12-23 17:58 編輯 ]

論壇徽章:
3
金牛座
日期:2014-06-14 22:04:062015年辭舊歲徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:49:45
4 [報告]
發(fā)表于 2008-12-23 19:47 |只看該作者
我不知道你這個等待隊列是不是使用了互斥的喚醒機(jī)制

論壇徽章:
0
5 [報告]
發(fā)表于 2008-12-23 21:13 |只看該作者

回復(fù) #1 taylergreen 的帖子

邏輯錯誤

論壇徽章:
0
6 [報告]
發(fā)表于 2008-12-24 12:36 |只看該作者

回復(fù) #5 kns1024wh 的帖子

啊 請達(dá)人明示 哈子

論壇徽章:
0
7 [報告]
發(fā)表于 2008-12-24 12:44 |只看該作者

回復(fù) #4 dreamice 的帖子

才接觸linux,對隊列的這些還不太懂。一會再看一下。
在代碼中,是參照網(wǎng)上的例子,申明了一下,后面就直接用了:
DECLARE_WAIT_QUEUE_HEAD(mcard_read_queue);
DECLARE_WAIT_QUEUE_HEAD(mcard_write_queue);

感覺問題不在這里。每次進(jìn)入 mcard_make_request 的進(jìn)程 就只有一個。

論壇徽章:
0
8 [報告]
發(fā)表于 2008-12-24 13:31 |只看該作者

回復(fù) #1 taylergreen 的帖子

剛仔細(xì)測試了一下   發(fā)現(xiàn)以前測試的方法有問題
現(xiàn)在發(fā)現(xiàn) 每次可以有多個進(jìn)程進(jìn)入make_request。
困惑的問題解決了。

剩下的確實是驅(qū)動邏輯的問題。等解決不了再來討教。
謝謝二位 牛人的熱情幫助。

論壇徽章:
0
9 [報告]
發(fā)表于 2008-12-24 15:07 |只看該作者

回復(fù) #5 kns1024wh 的帖子

還是想知道一下 邏輯錯誤有那些?

論壇徽章:
0
10 [報告]
發(fā)表于 2008-12-25 10:01 |只看該作者

回復(fù) #5 kns1024wh 的帖子

是不是這段有錯誤                 

                        dma_read_flag = 0;
                        MCARD_START_DMA_WRITE(addr, local_addr, byte_count);
                        wait_event_interruptible(mcard_read_queue, dma_read_flag == 1));

flag = 0應(yīng)該放在wait的后面?
您需要登錄后才可以回帖 登錄 | 注冊

本版積分規(guī)則 發(fā)表回復(fù)

  

北京盛拓優(yōu)訊信息技術(shù)有限公司. 版權(quán)所有 京ICP備16024965號-6 北京市公安局海淀分局網(wǎng)監(jiān)中心備案編號:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年舉報專區(qū)
中國互聯(lián)網(wǎng)協(xié)會會員  聯(lián)系我們:huangweiwei@itpub.net
感謝所有關(guān)心和支持過ChinaUnix的朋友們 轉(zhuǎn)載本站內(nèi)容請注明原作者名及出處

清除 Cookies - ChinaUnix - Archiver - WAP - TOP