·¢²©ÎÄ
ÈËÉúÖ®ÂÃ

http://blog.chinaunix.net/space.php?uid=20729605

ΪÃ÷ÈÕÖ®áÈÆð×ö½ñÈÕÖ®·Ü¶·£¬FIGHTING!   
¸öÈË×ÊÁÏ
  • ²©¿Í·ÃÎÊ£º278982
  • ²©ÎÄÊýÁ¿£º114
  • ²©¿Í»ý·Ö£º7079
  • ²©¿ÍµÈ¼¶£ºÉÙ½«
  • ¹Ø×¢ÈËÆø£º 2
  • ×¢²áʱ¼ä£º2008-07-14 11:24:44
¶©ÔÄÎҵIJ©¿Í
  • ¶©ÔÄ
  • ¶©Ôĵ½Ïʹû
  • ¶©Ôĵ½×¥Ïº
  • ¶©Ôĵ½Google
×ÖÌå´óС£º´ó ÖРС²©ÎÄ
·ÖÀࣺ LinuxÄÚºËѧϰ

     ÔÚÎÒдµÄǰһ¸öÕâÑùµÄÀý×ÓÀÓÉÓÚ²Ö¿â¿ÉÒÔ´æ·Å²úÆ·µÄλÖÃÖ»ÓÐÒ»¸ö£¬ËùÒÔÉú²úÕߺÍÏû·ÑÕßÖ»ÄÜÊÇÉú²úÒ»¸ö£¬Ïû·ÑÒ»¸ö£¬Ò²¾ÍÊǰ´²úÆ·µÄÉú²úÈÕÆÚ½øÐÐÏû·Ñ£¬Éú²úÔçµÄÏßÏû·Ñ¡£ÄÇÔÚÏÖʵÖУ¬ÍùÍù²»ÊÇÕâÑùµÄ¡£±ÈÈçÒ»¸ö²Ö¿âºÜ´óµÄʱºò£¬¿ÉÒԷźܶà²úÆ·£¬Éú²úÔçµÄÓпÉÄܱ»»ýѹÔÚÏÂÃæ£¬¶øºóÓÚÉú²ú³ÙµÄ²úÆ·±»Ïû·Ñ¡£ËùÒԸóÌÐò¾Í¿¼ÂÇÁËÕâÒ»ÏÖʵÎÊÌ⣬ģÄâÉú²úÕߺÍÏû·ÑÕßµÄÐÐΪ¹ý³Ì¡£¿öÇÒÔÚʵ¼ÊÉú²úÖУ¬ÓпÉÄÜÓкܶàÉú²ú³§ÉÌÉú²úͬһ¸ö²úÆ·£¬Ò²¿ÉÄÜÓкܶà¸öÏû·ÑÕßÏû·Ñ²úÆ·£¬ËùÒÔ±¾³ÌÐòÒ²¿ÉÒÔÄ£ÄâÕâÖÖÇé¿ö(½«×¢Ê͵ôµÄkernel_threadÌí¼ÓÉϾͿÉÒÔÁË)¡£ÒÔÏÂÊÇ´úÂ룺

#include<linux/init.h>
#include<linux/module.h>
#include<linux/wait.h>
#include<linux/sem.h>
#include<linux/sched.h>
#define BUFF_SIZE 10 /*²Ö¿âÖÐÓÐÊ®¸öλÖÿÉÒÔ´æ·Å²úÆ·*/
/*
 * _PRODUCE:    ±êʶÉú²úÕßµÄ״̬£º
 * RUNNING:     Éú²úÖÐ
 * STOPPED:      Í£Ö¹Éú²ú
 */

typedef enum _PRODUCE{RUNNING,STOPPED}PRODUCE;
/*
 * _storage:    ²úÆ·´æ·ÅµØ
 * buff :         ²Ö¿â
 * lock:          ²Ö¿âÃÅËø£¬Ò»¸öʱ¼äÖ»ÄÜÔÊÐíÉú²úÕß´æ·Å²úÆ·»òÕßÖ»ÔÊÐíÏû·ÑÕßÏû·Ñ²úÆ·
 * amount:     ²úÆ·ÏÖÓеĸöÊý
 * state:         Éú²úÕßµÄÉú²ú״̬
 * (*wait):       Ëø¶¨²Ö¿âÃÅ
 * (*signal):    ¿ªÆô²Ö¿âÃÅ
 */

struct _storage {
    char buff[BUFF_SIZE][20];
    struct semaphore lock;
    int amount;
    PRODUCE state;
    void (*wait)(struct semaphore *lock);
    void (*signal)(struct semaphore *lock);
};
/*
 * procon_lock:   ²úÆ·ÊýÁ¿¼ì²éËø
 * (*wait):            µÈ´ýÓвúÆ·¿ÉÒÔÏû·Ñ»òÕßÊǵȴý²Ö¿âÓÐλÖÿÉÒԷŲúÆ·
 * (*signla):         Ïû·Ñ²úÆ·»òÕß´æ·Å²úÆ··µ»Ø
 */

struct procon_lock {
    struct _storage *storage;
    void (*wait)(struct _storage *storage);
    void (*signal)(struct _storage *storage);
};

/*
 * _lock:         ´ò°ü¸÷ÖÖ×ÊÔ´
 * *storage:    ²Ö¿â×ÊÔ´
 * *empty:      µÈ´ý²Ö¿âÓÐλÖÿÉÒÔ´æ·Å²úÆ·
 * *full:           µÈ´ý²Ö¿âÀïÓвúÆ·¿ÉÒÔÏû·Ñ
 */

struct _lock {
    struct _storage *storage;
    struct procon_lock *empty;
    struct procon_lock *full;
};

void empty_wait(struct _storage *storage);
void empty_signal(struct _storage *storage);
void full_wait(struct _storage *storage);
void full_signal(struct _storage *storage);
int producer(void *p);
int consumer(void *p);
/*
 * storage:    ²Ö¿â
 */

struct _storage storage = {
    .amount=0, /*³õʼ²Ö¿âÖÐûÓвúÆ·*/
    .state=RUNNING,
    .wait=down,
    .signal=up,
};
/*
 * empty:        µÈ´ý²Ö¿âÓÐλÖ÷½²úÆ·Ëø
 */

struct procon_lock empty = {
    .storage=&storage,
    .wait=empty_wait,
    .signal=empty_signal,
};
/*
 * full:        µÈ´ý²Ö¿âÓвúÆ·¿ÉÒÔÏû·ÑËø
 */

struct procon_lock full = {
    .storage=&storage,
    .wait=full_wait,
    .signal=full_signal,
};
/*
 * lock:    ´ò°ü×ÊÔ´£¬½«Æä´«µÝ¸øÉú²úÕߺÍÏû·ÑÕß
 */

struct _lock lock = {
    .storage = &storage,
    .empty = &empty,
    .full = &full
};

MODULE_LICENSE("Dual BSD/GPL");
/*
 * procon_init:    ÄÚºËÄ£¿é³õʼ»¯º¯Êý
 */

static int procon_init(void)
{
    printk(KERN_INFO"Resolving the proceducer-consumer problem\n");
    memset(storage.buff,'\0',BUFF_SIZE*20);/*Çå¿Õ²Ö¿â*/
    init_MUTEX(&storage.lock); /*´ò¿ª²Ö¿âÃÅ*/

    //kernel_thread(producer,&lock,CLONE_KERNEL);
    //kernel_thread(producer,&lock,CLONE_KERNEL);
    kernel_thread(producer,&lock,CLONE_KERNEL); /*Æô¶¯Éú²úÏߣ¬Éú²úÕß¿ªÊ¼Éú²ú²úÆ·*/
    kernel_thread(consumer,&lock,CLONE_KERNEL);/*Ïû·ÑÕß¿ªÊ¼Ïû·Ñ²úÆ·*/
    //kernel_thread(consumer,&lock,CLONE_KERNEL);

    return 0;
}
/*
 * procon_exit:    ÄÚºËÄ£¿éÐ¶ÔØº¯Êý
 */

static void procon_exit(void)
{
    printk(KERN_INFO"Resolved the proceducer-consumer problem\n");
}


/*
 * producer:    Éú²úÕߣ¬¸ºÔðÉú²ú¶þÊ®¸ö²úÆ·
 * £À*p:           Éú²úÐèÒªµÄ×ÊÔ´
 */

int producer(void *p)
{
    struct _lock *lock=(struct _lock *)p; /*½â°ü×ÊÔ´*/
    struct _storage *storage=lock->storage;/*»ñÈ¡²Ö¿â×ÊÔ´*/
    struct procon_lock *empty=lock->empty;/*»ñÈ¡²Ö¿âλÖÃ̽²â×ÊÔ´*/
    struct procon_lock *full=lock->full;/*»ñÈ¡²Ö¿âλÖÃ̽²â×ÊÔ´*/
    struct task_struct *task=current;/*È¡µÃµ±Ç°Ïß³ÌÃèÊö·û*/
    int i,j;
    
    printk(KERN_INFO"%d:producer start produce products...\n",task->pid);/*ÏÔʾ¿ªÊ¼Éú²ú*/
    for(i=0;i<20;i++) { /*×ܹ²Éú²ú¶þÊ®¸ö²úÆ·*/
        empty->wait(empty->storage); /*Èç¹û²Ö¿âÒѾ­·ÅÂú£¬ÔòµÈ´ýÖ±µ½ÓÐλÖÿÉÒԷŲúÆ·*/
        storage->wait(&storage->lock);/*´ò¿ª²Ö¿âÃÅ*/
        for(j=0;j<BUFF_SIZE;j++) { /*ѰÕÒÒ»¸ö¿ÉÒԷŲúÆ·µÄλÖÃ*/
            if(!strlen(storage->buff[j]))
                break;
        }

        snprintf(storage->buff[j],20,"%d:product-%d",task->pid,i);/*Éú²ú²úÆ·£¬·ÅÈë²Ö¿â*/
        printk(KERN_INFO"%d:producer produce %s\n",task->pid,storage->buff[j]);/*Éú²úÕßÌáʾÒѾ­Éú²ú*/
        full->signal(full->storage);/*ÌáʾÏû·ÑÕßÓвúÆ·¿ÉÒÔÏû·Ñ*/
        storage->signal(&storage->lock);/*¹Ø±Õ²Ö¿âÃÅ*/
    }
    storage->state=STOPPED;/*Éú²úÍê±Ï£¬¹Ø±ÕÉú²úÏß*/
    printk(KERN_INFO"%d:producer exit...\n",task->pid); /*Í˳öÉú²ú*/
    return 0;
}
/*
 * consumer:    Ïû·ÑÕߣ¬Èç¹ûÓвúÆ·£¬ÔòÏû·Ñ²úÆ·
 * @*p:            Ïû·ÑÐèÒªµÄ×ÊÔ´
 */

int consumer(void *p)
{
    struct _lock *lock=(struct _lock *)p;
    struct _storage *storage=lock->storage;
    struct procon_lock *empty=lock->empty;
    struct procon_lock *full=lock->full;
    struct task_struct *task=current;
    int i;
    printk(KERN_INFO"%d:consumer start consume products...\n",task->pid);/*Ìáʾ¿ªÊ¼Ïû·Ñ*/
    for(;;) {
        /*Èç¹û²Ö¿âÖÐÒѾ­Ã»ÓвúÆ·²¢ÇÒÉú²úÕßÒѾ­Í˳öÉú²úÏߣ¬ÔòÍ£Ö¹Ïû·Ñ*/
        if(storage->amount==0&&storage->state==STOPPED){
            break;
        }
        
        full->wait(full->storage); /*Èç¹û²Ö¿âÃÅûÓвúÆ·£¬ÔòµÈ´ýÖ±µ½ÓвúÆ·*/
        storage->wait(&storage->lock);/*´ò¿ª²Ö¿âÃÅ*/
        for(i=0;i<BUFF_SIZE;i++) {/*ѰÕÒÒ»¸ö²úÆ·*/
            if(strlen(storage->buff[i]))
                break;
        }
        
        printk(KERN_INFO"%d:consumer consume %s\n",task->pid,storage->buff[i]);/*Ïû·ÑÕßÌáʾ»ñµÃÁ˲úÆ·*/
        memset(storage->buff[i],'\0',20);/*Ïû·Ñ²úÆ·*/
        empty->signal(empty->storage);/*¸æËßÉú²úÕß²Ö¿âÓÐλÖÿÉÒԷŲúÆ·*/        
        storage->signal(&storage->lock); /*¹Ø±Õ²Ö¿âÃÅ*/
    }
    printk(KERN_INFO"%d:consumer exit...\n",task->pid);
    return 0;
}
/*
 * empty_wait:    µÈ´ý²Ö¿âÖÐÓÐλÖÿÉÒԷŲúÆ·
 * @storage:      ²Ö¿â
 */

void empty_wait(struct _storage *storage)
{
    do {
        if(storage->amount<BUFF_SIZE) /*Èç¹û²Ö¿âÖÐÓÐλÖÿÉÒԷŲúÆ·£¬ÔòÍ˳öµÈ´ý*/
            break;
        schedule();/*µÈ´ý²Ö¿âÖÐÓпÕλÖÃ*/
    }while(1);
}
/*
 * empty_signal:    Í¨ÖªÉú²úÕßÕß²Ö¿âÖÐÓÐλÖÿÉÒԷŲúÆ·
 * @*storage:        ²Ö¿â
 */

void empty_signal(struct _storage *storage)
{
    storage->amount--; /*²úÆ·¼ÆÊý¼õÒ»*/
}
/*
 * full_wait:        µÈ´ý²Ö¿âÖÐÓвúÆ·¿ÉÒÔÏû·Ñ
 * @*storage:    ²Ö¿â
 */

void full_wait(struct _storage *storage)
{
    do {
        if(storage->amount>0) /*Èç¹û²Ö¿âÖÐÓвúÆ·¿ÉÒÔÏû·Ñ£¬Ôò·µ»Ø*/
            break;
        schedule();/*µÈ´ýÓвúÆ·*/
    }while(1);
}
/*
 * full_signal:    Í¨ÖªÏû·ÑÕß²Ö¿âÖÐÓвúÆ·¿ÉÒÔÏû·Ñ
 * @*storage:   ²Ö¿â
 */

void full_signal(struct _storage *storage)
{
        storage->amount++; /*²úÆ·¼ÆÊý¼ÓÒ»*/
}

module_init(procon_init);
module_exit(procon_exit);
MODULE_AUTHOR("Niu Tao");
MODULE_DESCRIPTION("The proceducer-consumer problem");
MODULE_ALIAS("a simplest module");


Makefile:

obj-m :=procon.o
CURRENT_PATH := $(shell pwd)
LINUX_KERNEL := $(shell uname -r)
LINUX_KERNEL_PATH := /usr/src/linux-headers-$(LINUX_KERNEL)

all:
    make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) modules
clean:
    rm -rf .*.cmd *.o *.mod.c *.ko .tmp_versions Module.symvers .Makefile.swp


³ÌÐòÔËÐнá¹û£º

[13899.280451] Resolving the proceducer-consumer problem
[13899.284977] 16104:producer start produce products...
[13899.284984] 16104:producer produce 16104:product-0
[13899.284987] 16104:producer produce 16104:product-1
[13899.284990] 16104:producer produce 16104:product-2
[13899.284992] 16104:producer produce 16104:product-3
[13899.284994] 16104:producer produce 16104:product-4
[13899.284997] 16104:producer produce 16104:product-5
[13899.284999] 16104:producer produce 16104:product-6
[13899.285002] 16104:producer produce 16104:product-7
[13899.285004] 16104:producer produce 16104:product-8
[13899.285007] 16104:producer produce 16104:product-9
[13899.339264] 16105:consumer start consume products...
[13899.339495] 16105:consumer consume 16104:product-0
[13899.339633] 16104:producer produce 16104:product-10
[13899.339769] 16105:consumer consume 16104:product-10
[13899.339907] 16104:producer produce 16104:product-11
[13899.340042] 16105:consumer consume 16104:product-11
[13899.340208] 16104:producer produce 16104:product-12
[13899.340344] 16105:consumer consume 16104:product-12
[13899.340481] 16104:producer produce 16104:product-13
[13899.340616] 16105:consumer consume 16104:product-13
[13899.340887] 16104:producer produce 16104:product-14
[13899.341036] 16105:consumer consume 16104:product-14
[13899.341175] 16104:producer produce 16104:product-15
[13899.341310] 16105:consumer consume 16104:product-15
[13899.341447] 16104:producer produce 16104:product-16
[13899.341582] 16105:consumer consume 16104:product-16
[13899.341719] 16104:producer produce 16104:product-17
[13899.341854] 16105:consumer consume 16104:product-17
[13899.342029] 16104:producer produce 16104:product-18
[13899.342164] 16105:consumer consume 16104:product-18
[13899.342302] 16104:producer produce 16104:product-19
[13899.342305] 16104:producer exit...
[13899.342525] 16105:consumer consume 16104:product-19
[13899.342663] 16105:consumer consume 16104:product-1
[13899.342808] 16105:consumer consume 16104:product-2
[13899.343060] 16105:consumer consume 16104:product-3
[13899.343214] 16105:consumer consume 16104:product-4
[13899.343352] 16105:consumer consume 16104:product-5
[13899.343489] 16105:consumer consume 16104:product-6
[13899.343625] 16105:consumer consume 16104:product-7
[13899.343762] 16105:consumer consume 16104:product-8
[13899.343899] 16105:consumer consume 16104:product-9
[13899.343902] 16105:consumer exit...
[14598.468929] Resolved the proceducer-consumer problem

²©¿ÍÍÆ¼öÎÄÕÂ
Ç×£¬Äú»¹Ã»ÓеǼ,Çë[µÇ¼]»ò[×¢²á]ºóÔÙ½øÐÐÆÀÂÛ