每当给学生讲起操作系统中的并发,学生总会以疑惑的神情思考这个貌似陌生的问题。因为从C语言一路走来,程序的执行铁定了是一条一条顺序执行的,即使我们要解决的问题并非线性,但在串行化的世界,我们一定要把复杂的问题拉扯成线性。于是乎,串行执行成为理所当然,而并发成为突发而出的概念。可是,回到现实世界看看,并发才是常态。在商品经济的大潮中,有谁告诉该哪些厂家生成多少手机,又有谁告诉多少购买者购何种手机?经济危机又是怎样发生的?计划经济起到怎样的杠杆作用?如此一系列的问题,似乎是社会问题,实际上何尝不是计算机系统中的问题。在操作系统的教科书中,生产者-消费者的经典实例总会粉墨登场,但一般也只是把它作为考试的拦路虎并不与现实实际做过多的联系。而实际上,所谓模型,它抽象了若干种现实实例,反过来说,把这一模型推而广之,可以应用到若干种场合。
口头上说说这样的模型并非难事,但落实到代码才算从云端踏入大地。好在,每次当我说完云端的概念,有学生总会把它变为代码放在自己的博客上供大家分享。在此,我也从他的博客上搬来用内核线程实现的生产者-消费者模型: ------------------------------------------------------------------------------------------------------------------------------------------------------
在IPC系列文章当中,利用信号量集实现的是用户态下生产者-消费者模型的模型。本文以内核模块的方式,通过创建内核线程来为大家演示内核态下的生产者消费者模型。本模型属于np-nc-nb,即多个生产者多个消费者多个缓冲区。
在加载函数中,完成一些初始化的工作,并分别创建了5个生产者线程和消费者线程。kernel_thread函数的第一个参数是所所创建线程要做的动作;通过第二个参数传递i变量。
|
01
|
static int __init np_nc_init(void)
|
|
02
|
{
|
|
05
|
printk("np_nc module is
working..\n");
|
|
06
|
in=out=0;
|
|
07
|
cflag=0;
|
|
08
|
init_MUTEX(&mutex);
|
|
09
|
sema_init(&s1,BUF_NUM);
|
|
10
|
sema_init(&s2,0);
|
|
15
|
kernel_thread(productor_thread,&(index[i]),CLONE_KERNEL);
|
|
16
|
kernel_thread(consumer_thread,&(index[i]),CLONE_KERNEL);
|
在生产者函数中,PNUM是每个生产者要生产货物的数量。语句buf[in]=i*100+(PNUM-p_num+1)即是产生货物的过程。
|
01
|
int productor_thread(void *p)
|
|
02
|
{
|
|
03
|
int i=*(int *)p;
|
|
04
|
int p_num=PNUM;
|
|
07
|
{
|
|
08
|
if((s1.count)<=0)
|
|
09
|
{
|
|
10
|
printk("[producer
%d,%d]:I will be waiting for producting..\n",i,s1.count);
|
|
13
|
down(&mutex);
|
|
14
|
buf[in]=i*100+(PNUM-p_num+1);
|
|
15
|
printk("[producer
%d,%d]:I producted a goods \"%d\" to
buf[%d]..\n",i,s1.count,buf[in],in);
|
|
16
|
in=(in+1)%BUF_NUM;
|
|
17
|
up(&mutex);
|
|
18
|
up(&s2);
|
在消费者函数中,通过一个全局变量CNUM来控制消费者总共的消费次数。
|
01
|
int consumer_thread(void *p)
|
|
02
|
{
|
|
03
|
int i=*(int *)p;
|
|
04
|
int goods;
|
|
07
|
{
|
|
08
|
if((s2.count)<=0)
|
|
09
|
{
|
|
10
|
printk("[consumer
%d,%d]:I will be waiting for goods..\n",i,s2.count);
|
|
13
|
down(&mutex);
|
|
14
|
goods=buf[out];
|
|
15
|
printk("[consumer
%d,%d]:I consumed a goods \"%d\" from
buf[%d]..\n",i,s2.count,goods,(out%BUF_NUM));
|
|
16
|
out=(out+1)%BUF_NUM;
|
|
17
|
up(&mutex);
|
|
18
|
up(&s1);
|
更多内容参看他的博客:http://www.edsionte.com/
本文内容由 陈莉君 提供 |