Linux多進程實例與代碼優化

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <pthread.h>

#define BUFFER_SIZE 16

struct prodcons
{
	int buffer[BUFFER_SIZE];
	pthread_mutex_t lock;
	int readpos,writepos;
	pthread_cond_t notempty;
	pthread_cond_t notfull;
};

void init(struct prodcons* b)
{
	pthread_mutex_init(&b->lock,NULL);
	pthread_cond_init(&b->notempty,NULL);
	pthread_cond_init(&b->notfull,NULL);
	b->readpos = 0;
	b->writepos = 0;
}

void put(struct prodcons* b,int data)
{
	pthread_mutex_lock(&b->lock);
	while((b->writepos +1)%BUFFER_SIZE==b->readpos)
	{
		printf("wait for not full.\n");
		pthread_cond_wait(&b->notfull,&b->lock);
	}
	b->buffer[b->writepos] = data;
	b->writepos++;
	if(b->writepos >= BUFFER_SIZE)b->writepos=0;
	pthread_cond_signal(&b->notempty);
	pthread_mutex_unlock(&b->lock);
}

int get(struct prodcons *b)
{
	int data;
	pthread_mutex_lock(&b->lock);
	while(b->writepos == b->readpos)
	{
		printf("wait for not empty");
		pthread_cond_wait(&b->notempty,&b->lock);
	}
	data = b->buffer[b->readpos];
	b->readpos++;
	if(b->readpos >=BUFFER_SIZE)b->readpos=0;
	pthread_cond_signal(&b->notfull);
	pthread_mutex_unlock(&b->lock);
	return data;
}

#define OVER (-1)
struct prodcons buffer;

void *producer(void* data)
{
	int n;
	for(n=0;n<100;n++)
	{
		printf("put---->%d.\n",n);
		put(&buffer,n);
	}
	put(&buffer,OVER);
	printf("producer stopped!\n");
	return NULL;
}

void *consumer(void *data)
{
	int d;
	while(1)
	{
		d = get(&buffer);
		if(d==OVER)break;
		printf("        %d---->get.\n",d);
	}
	printf("consumer stopped!\n");
	return NULL;
}

int main(void)
{
	pthread_t th_a,th_b;
	void *retval;
	init(&buffer);
	pthread_create(&th_a,NULL,producer,0);
	pthread_create(&th_b,NULL,consumer,0);
	pthread_join(th_a,&retval);
	pthread_join(th_b,&retval);
	return 0;
}

這時一個生產者與消費者的程序,程序實現了生產者與消費者並行運行,並且共用一個緩存區。其中使用到一個互斥鎖和信號量來共同控制對緩存區的互斥訪問,緩存的狀態(空,滿)的協調。但是全都在一個文件之中以至於main.c十分臃腫,下面時自己的進行的代碼優化

main.c

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <pthread.h>
#include "pro_con.h"

int main(void)
{
	pthread_t th_a,th_b;
	void *retval;
	fun.init(&buffer);
	pthread_create(&th_a,NULL,fun.producer,0);
	pthread_create(&th_b,NULL,fun.consumer,0);
	pthread_join(th_a,&retval);
	pthread_join(th_b,&retval);
	return 0;
}
pro_con.c

//------------------Include Files--------------------------------
#include <stdio.h>
#include <pthread.h>
#include "pro_con.h"
//-------------------------Function Prototype------------------------
static void c_init(struct prodcons* b);	          		    //初始化信號量
static void c_put(struct prodcons* b,int data);	  	 	    //向緩存中放入數據
static int c_get(struct prodcons* b);
static void* c_producer(void* data);
static void* c_consumer(void* data);


//---------------------------Variable-----------------------------
prodcons_fun fun=
{
	c_init,
	c_put,
	c_get,
	c_producer,
	c_consumer
};
struct prodcons buffer;

/*
 *============Function=======================================
 * Name         :   init
 * Description  :   初始化緩存指針信息
 *============================================================
 */ 
static void c_init(struct prodcons* b)               //初始化信號量
{
	pthread_mutex_init(&b->lock,NULL);
	pthread_cond_init(&b->notempty,NULL);
	pthread_cond_init(&b->notfull,NULL);
	b->readpos = 0;
	b->writepos = 0;
}
/*
 *============Function========================================
 * Name             : put
 * Description      :向緩存中放入數據
 *=============================================================
 */

static void c_put(struct prodcons* b,int data)
{
	pthread_mutex_lock(&b->lock);
	while((b->writepos + 1)%BUFFER_SIZE==b->readpos)
	{
		printf("wait for not full.\n");
		pthread_cond_wait(&b->notfull,&b->lock);
	}
	b->buffer[b->writepos] = data;
	b->writepos++;
	if(b->writepos >= BUFFER_SIZE)b->writepos=0;
	pthread_cond_signal(&b->notempty);
	pthread_mutex_unlock(&b->lock);
}

/*
 *===========Function===========================================
 * Name                 :get
 * Description          :從緩存中獲取數據
 *=============================================================
 */
static int c_get(struct prodcons* b)
{
	int data;
	pthread_mutex_lock(&b->lock);
	while(b->writepos == b->readpos)
	{
		printf("wait for not empty");
		pthread_cond_wait(&b->notempty,&b->lock);
	}
	data = b->buffer[b->readpos];
	b->readpos++;
	if(b->readpos >= BUFFER_SIZE)b->readpos=0;
	pthread_cond_signal(&b->notfull);
	pthread_mutex_unlock(&b->lock);
	return data;
}

/*
 *================Function========================================
 * Name                :producer
 * Description          :實現一個生產者程序,當生產-1時,程序終止
 *===============================================================
 */
static void* c_producer(void* data)
{
	int n;
	for(n=0;n<100;n++)
	{
		printf("put---->%d.\n",n);
		c_put(&buffer,n);
	}
	c_put(&buffer,OVER);
	printf("producer stopped!\n");
	return NULL;
}

/*
 *==============Function======================================
 * Name               :consumer
 * Description        :消費掉緩存中生產出來的數據,當消費-1時,程序終止
 *=================================================================
 */
static void* c_consumer(void *data)
{
	int d;
	while(1)
	{
		d = c_get(&buffer);
		if(d==OVER)break;
		printf("        %d---->get.\n",d);
	}
	printf("consumer stopped!\n");
	return NULL;
}
pro_con.h

//---------------Defines----------------------------------
#define OVER (-1)          //結束標誌
#define BUFFER_SIZE 16     //使用緩存大小


//--------------Type define-----------------------------------------
struct prodcons
{
	int buffer[BUFFER_SIZE];   //緩存申請
	pthread_mutex_t lock;      //緩存鎖
	int readpos,writepos;      //讀寫的位置指針
	pthread_cond_t notempty;  // 不空的信號量
	pthread_cond_t notfull;   //不滿的信號量
};

typedef struct 
{
	void (*init)(struct prodcons* b);             //初始化緩存信息
	void (*put)(struct prodcons* b,int data);     //向緩存中放入數據
	int (*get)(struct prodcons* b);		  //從緩存中獲得數據
	void* (*producer)(void* data);		  //
	void* (*consumer)(void* data);		  //
}prodcons_fun;
//-------------Extern----------------------------------------------
extern prodcons_fun fun;
extern struct prodcons buffer;

下面主要是講講extern關鍵字與static關鍵字(來源百度百科),以及在把函數封裝在結構體之中。

extern:

extern可以置於變量或者函數前,以表示變量或者函數的定義在別的文件中,提示編譯器遇到此變量和函數時在其他模塊中尋找其定義。例如:在main.c中根本沒有聲明變量fun與buffer,但是確可以直接使用。extern的原理很簡單,就是告訴編譯器:“你現在編譯的文件中,有一個標識符雖然沒有在本文件中定義,但是它是在別的文件中定義的全局變量,你要放行!”如extern int a;僅僅是一個變量的聲明,其並不是在定義變量a,並未爲a分配內存空間。變量a在所有模塊中作爲一種全局變量只能被定義一次,否則會出現連接錯誤。


static:

當用static修飾變量或者函數的時候,這個變量或者函數將變爲靜態的,變爲靜態的有下面幾個好處:一:靜態全局變量不能被其它文件所用;二:不同的人編寫不同的函數時,不用擔心自己定義的函數,是否會與其它文件中的函數同名,因爲同名也沒有關係。


最後在prodcons_fun這個結構體中把所有用到的函數都封裝了起來,在此要注意這個結構體的成員永遠是  init,put,get,producer,consumer,這五個,因此當fun被初始化爲c_init,c_put,c_get,c_producer,c_consumer時,最後調用,還是使用 init,put,get,producer,consumer。因爲爲初始化的過程中,只是把這幾個具體實現函數的函數指針(函數入口地址)傳遞給了 init,put,get,producer,consumer,這些成員。

還要注意的是,在編譯時,需要加上 -l pthread,因爲pthread不是默認鏈接的函數庫,如果不加,就會出現找不到有關進程的一些相互函數。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章