Linux信號量機制

1 需求說明

1.1 基本需求

目標:

本次實驗的目標是在Linux環境下實現一個多線程對臨界資源的互斥操作,利用信號量實現對臨界資源的保護,支持Linux下文件輸入輸出,提高對Linux環境下多進程、多線程、信號量機制和文件操作等知識的理解。

問題描述:

設有進程A、B、C,分別調用過程get、copy、put對緩衝區S和T進行操作。其中get負責從文件F_in中把數據塊讀入並輸出緩衝區S,copy負責從S中提取數據塊並複製到緩衝區T中,put負責從緩衝區T中取出信息存入到本地文件F_out中。實現get、copy、put的操作過程。


功能需求:

l 提供與用戶交互的界面,用戶可指定輸入、輸出文件以及緩衝區大小

l 利用信號量實現互斥

l 同時產生多個get、copy和put線程,利用信號量實現多個相同功能的線程間的通信,避免臨界資源的非法訪問,可參考讀寫者問題解決方案

l 支持文件輸入、輸出

非功能需求:

l  程序應有較好的容錯性(即能對用戶輸入的命令進行判斷,並對錯誤的命令進行錯誤處理)

過程需求:

l  使用vi進行代碼的編寫

l 使用make工具建立工程

l 將實現不同類別功能的函數寫到不同的.c文件中,並使用makefile鏈接編譯。

 

2 設計說明

2.1 結構設計

三個信號量實現線程互斥

sem_tread_sem; // read

sem_twrite_sem; // write

sem_tcopy_sem; // copy

2.2 功能設計

實現了同步多線程運行,文件讀入,緩衝區COPY,文件寫入三個線程同時運行,完成LINUX下文件的輸入輸出。

文件讀入:用linux下open(),read(),lseek()函數實現

文件寫出:用linux下open(),write()實現

緩衝區建立 malloc()函數

信號量建立sem_init(),sem_wait(),sem_post()

互斥量建立pthread_create(),pthread_mutex_lock(),pthread_mutex_unlock()

 

3 測試和使用說明

3.1 使用說明

使用./signalmove啓動程序,啓動參數必須包括,寫入文件名,寫出的文件名,和緩衝區大小,否則會報錯退出。

緩衝區大小必須爲數字,否則退出。

4 程序清單

OBJS=main.o copy.o get.o put.o file.o
signalmove:$(OBJS) signalmove.h
	gcc $(OBJS) -o signalmove -lpthread
main.o:main.c signalmove.h
	gcc -c main.c -lpthread
copy.o:copy.c signalmove.h
	gcc -c copy.c
get.o:get.c signalmove.h
	gcc -c get.c
put.o:put.c signalmove.h
	gcc -c put.c
file.o:file.c signalmove.h
	gcc -c file.c

/*
 * signalmove.h
 *
 *  Created on: May 14, 2012
 *      Author: dell
 */

#ifndef SIGNALMOVE_H_
#define SIGNALMOVE_H_

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>
#include <signal.h>
#include <fcntl.h>
#include <string.h>
#include <ctype.h>

//file works
void file_in();
void file_out();
//copy from s to t
void copy();
//put and get
void put();
void get();

sem_t read_sem; // read
sem_t write_sem; // write
sem_t copy_sem; // copy

pthread_mutex_t read_mutex; // pthread mutex for read
pthread_mutex_t write_mutex; // pthread mutex for write

char *data_s; //read buffer
char *data_t; //write buffer
int len; //buffer length

char *filename_out; //name_out
char *filename_in; //name_in

int result;
int result_copy;

#endif /* SIGNALMOVE_H_ */

/*
 * main.c
 *
 *  Created on: May 14, 2012
 *      Author: dell
 */
#include "signalmove.h"

int isdigit_all(char *str)
{
    while (*str != '\0')
    {
        if (!isdigit(*str++))
            return 0;
    }
    return 1;
}

//signal out
void Handlesignal(int signo) {
	printf("end program!\n", signo);
	exit(0);
}

void main(int argc, char* argv[]) {
	if(argc!=4){
		printf("error input! 1.filename_in,2.filename_out,3,length of buffer\n");
		exit(0);
	}
	if(isdigit_all(argv[3])==0){
		printf("error input! 1.filename_in,2.filename_out,3,length of buffer\n");
		printf("error length of buffer must be digit!\n");
		exit(0);
	}
	result_copy = 0;
	filename_in=argv[1];
	filename_out=argv[2];
	len=atoi(argv[3]);
	int thread_i = 0;
	data_s = (char *) malloc(len * sizeof(char));
	data_t = (char *) malloc(len * sizeof(char));

	if (signal(SIGINT, Handlesignal) == SIG_ERR) { 
		printf("error signal out\n");
	}
	pthread_t read_pthread;
	pthread_t copy_pthread;
	pthread_t write_pthread;

	//sem lock
	int ini1 = sem_init(&read_sem, 0, 1);
	int ini2 = sem_init(&write_sem, 0, 0);
	int ini5 = sem_init(©_sem, 0, 0);
	if (ini1 && ini2 && ini5 != 0) {
		printf("sem error\n");
		exit(1);
	}
	//mutex lock
	int ini3 = pthread_mutex_init(&read_mutex, NULL);
	int ini4 = pthread_mutex_init(&write_mutex, NULL);
	if (ini3 && ini4 != 0) {
		printf("mutex error\ n");
		exit(1);
	}
	int thread_1 = pthread_create(&read_pthread, NULL, (void *)&get,
			(void *) (&thread_i));
	if (thread_1 != 0) {
		printf("read thread create error!\n");
		exit(1);
	}
	thread_i++;
	int thread_2 = pthread_create(©_pthread, NULL, (void *)©,
			(void *) (&thread_i));
	if (thread_2 != 0) {
		printf("copy thread create error!\n");
		exit(1);
	}
	thread_i++;
	int thread_3 = pthread_create(&write_pthread, NULL, (void *)&put,
			(void *) (&thread_i));
	if (thread_3 != 0) {
		printf("write thread create error!\n");
		exit(1);
	}
	pthread_join(read_pthread, NULL);
	pthread_join(copy_pthread, NULL);
	pthread_join(write_pthread, NULL);
	free(data_s);
	free(data_t);
	exit(0);
}

/*
 * file.c
 *
 *  Created on: May 14, 2012
 *      Author:dell
 *  file works
 */
#include "signalmove.h"

void file_in(int fd, char *data, int len) {
	while (1) {
		sem_wait(&read_sem);
		pthread_mutex_lock(&read_mutex);
		printf("data_in..........\n");
		if (lseek(fd, 0, SEEK_CUR) == -1) {
			printf("lseek failed!\n");
		}
		if ((result = read(fd, data, len)) == -1) {
			printf("read error! \n");
		}
		int i=0,j=0;
		printf("data_in..........complete\n");
		pthread_mutex_unlock(&read_mutex);
		sem_post(©_sem);
		if(result<len){
			len=result;
			result=0;
			break;
		}
	}
}
void file_out(int fd, char *data, int len) {
	while (1) {
		sem_wait(&write_sem);
		pthread_mutex_lock(&write_mutex);
		printf("data_out..........\n");
		if (write(fd, data, len) == -1) {
			printf("write error! \n");
		}
		printf("data_out..........complete\n");
		pthread_mutex_unlock(&write_mutex);
		if(result_copy==1){
			break;
		}
	}
}

/*
 * put.c
 *
 *  Created on: May 14, 2012
 *      Author: dell
 */
#include "signalmove.h"

void put() {
	int fd = open(filename_out, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
	if (fd == -1) {
		printf("open file wrong!\n");
		exit(0);
	}
	file_out(fd, data_t, len);
}

/*
 * get.c
 *
 *  Created on: May 14, 2012
 *      Author: dell
 */
#include "signalmove.h"

void get() {
	int fd = open(filename_in, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
	if (fd == -1) {
		printf("open file wrong!\n");
		exit(0);
	}
	file_in(fd, data_s, len);
}

/*
 * copy.c
 *
 *  Created on: May 14, 2012
 *      Author: dell
 *  copy data from S to T
 */
#include "signalmove.h"

void copy() {
	while (1) {
		sem_wait(©_sem);
		pthread_mutex_lock(&read_mutex);
		pthread_mutex_lock(&write_mutex);
		printf("copy..........\n");
		strcpy(data_t,data_s);
		int i=0;
		for(;i<len;i++){
			data_s[i]=' ';
		}
		printf("copy..........complete\n");
		pthread_mutex_unlock(&write_mutex);
		pthread_mutex_unlock(&read_mutex);
		sem_post(&write_sem);
		sem_post(&read_sem);
		if (result == 0) {
			result_copy = 1;
			break;
		}
	}
}


發佈了35 篇原創文章 · 獲贊 20 · 訪問量 18萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章