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 程序清单

  1. OBJS=main.o copy.o get.o put.o file.o  

  2. signalmove:$(OBJS) signalmove.h  

  3.    gcc $(OBJS) -o signalmove -lpthread  

  4. main.o:main.c signalmove.h  

  5.    gcc -c main.c -lpthread  

  6. copy.o:copy.c signalmove.h  

  7.    gcc -c copy.c  

  8. get.o:get.c signalmove.h  

  9.    gcc -c get.c  

  10. put.o:put.c signalmove.h  

  11.    gcc -c put.c  

  12. file.o:file.c signalmove.h  

  13.    gcc -c file.c  

  14. /*

  15. * signalmove.h

  16. *

  17. *  Created on: May 14, 2012

  18. *      Author: dell

  19. */

  20. #ifndef SIGNALMOVE_H_

  21. #define SIGNALMOVE_H_

  22. #include <stdio.h>

  23. #include <stdlib.h>

  24. #include <unistd.h>

  25. #include <pthread.h>

  26. #include <semaphore.h>

  27. #include <signal.h>

  28. #include <fcntl.h>

  29. #include <string.h>

  30. #include <ctype.h>

  31. //file works

  32. void file_in();  

  33. void file_out();  

  34. //copy from s to t

  35. void copy();  

  36. //put and get

  37. void put();  

  38. void get();  

  39. sem_t read_sem; // read

  40. sem_t write_sem; // write

  41. sem_t copy_sem; // copy

  42. pthread_mutex_t read_mutex; // pthread mutex for read

  43. pthread_mutex_t write_mutex; // pthread mutex for write

  44. char *data_s; //read buffer

  45. char *data_t; //write buffer

  46. int len; //buffer length

  47. char *filename_out; //name_out

  48. char *filename_in; //name_in

  49. int result;  

  50. int result_copy;  

  51. #endif /* SIGNALMOVE_H_ */

  52. /*

  53. * main.c

  54. *

  55. *  Created on: May 14, 2012

  56. *      Author: dell

  57. */

  58. #include "signalmove.h"

  59. int isdigit_all(char *str)  

  60. {  

  61. while (*str != '\0')  

  62.    {  

  63. if (!isdigit(*str++))  

  64. return 0;  

  65.    }  

  66. return 1;  

  67. }  

  68. //signal out

  69. void Handlesignal(int signo) {  

  70.    printf("end program!\n", signo);  

  71.    exit(0);  

  72. }  

  73. void main(int argc, char* argv[]) {  

  74. if(argc!=4){  

  75.        printf("error input! 1.filename_in,2.filename_out,3,length of buffer\n");  

  76.        exit(0);  

  77.    }  

  78. if(isdigit_all(argv[3])==0){  

  79.        printf("error input! 1.filename_in,2.filename_out,3,length of buffer\n");  

  80.        printf("error length of buffer must be digit!\n");  

  81.        exit(0);  

  82.    }  

  83.    result_copy = 0;  

  84.    filename_in=argv[1];  

  85.    filename_out=argv[2];  

  86.    len=atoi(argv[3]);  

  87. int thread_i = 0;  

  88.    data_s = (char *) malloc(len * sizeof(char));  

  89.    data_t = (char *) malloc(len * sizeof(char));  

  90. if (signal(SIGINT, Handlesignal) == SIG_ERR) {  

  91.        printf("error signal out\n");  

  92.    }  

  93.    pthread_t read_pthread;  

  94.    pthread_t copy_pthread;  

  95.    pthread_t write_pthread;  

  96. //sem lock

  97. int ini1 = sem_init(&read_sem, 0, 1);  

  98. int ini2 = sem_init(&write_sem, 0, 0);  

  99. int ini5 = sem_init(©_sem, 0, 0);  

  100. if (ini1 && ini2 && ini5 != 0) {  

  101.        printf("sem error\n");  

  102.        exit(1);  

  103.    }  

  104. //mutex lock

  105. int ini3 = pthread_mutex_init(&read_mutex, NULL);  

  106. int ini4 = pthread_mutex_init(&write_mutex, NULL);  

  107. if (ini3 && ini4 != 0) {  

  108.        printf("mutex error\ n");  

  109.        exit(1);  

  110.    }  

  111. int thread_1 = pthread_create(&read_pthread, NULL, (void *)&get,  

  112.            (void *) (&thread_i));  

  113. if (thread_1 != 0) {  

  114.        printf("read thread create error!\n");  

  115.        exit(1);  

  116.    }  

  117.    thread_i++;  

  118. int thread_2 = pthread_create(©_pthread, NULL, (void *)©,  

  119.            (void *) (&thread_i));  

  120. if (thread_2 != 0) {  

  121.        printf("copy thread create error!\n");  

  122.        exit(1);  

  123.    }  

  124.    thread_i++;  

  125. int thread_3 = pthread_create(&write_pthread, NULL, (void *)&put,  

  126.            (void *) (&thread_i));  

  127. if (thread_3 != 0) {  

  128.        printf("write thread create error!\n");  

  129.        exit(1);  

  130.    }  

  131.    pthread_join(read_pthread, NULL);  

  132.    pthread_join(copy_pthread, NULL);  

  133.    pthread_join(write_pthread, NULL);  

  134.    free(data_s);  

  135.    free(data_t);  

  136.    exit(0);  

  137. }  

  138. /*

  139. * file.c

  140. *

  141. *  Created on: May 14, 2012

  142. *      Author:dell

  143. *  file works

  144. */

  145. #include "signalmove.h"

  146. void file_in(int fd, char *data, int len) {  

  147. while (1) {  

  148.        sem_wait(&read_sem);  

  149.        pthread_mutex_lock(&read_mutex);  

  150.        printf("data_in..........\n");  

  151. if (lseek(fd, 0, SEEK_CUR) == -1) {  

  152.            printf("lseek failed!\n");  

  153.        }  

  154. if ((result = read(fd, data, len)) == -1) {  

  155.            printf("read error! \n");  

  156.        }  

  157. int i=0,j=0;  

  158.        printf("data_in..........complete\n");  

  159.        pthread_mutex_unlock(&read_mutex);  

  160.        sem_post(©_sem);  

  161. if(result<len){  

  162.            len=result;  

  163.            result=0;  

  164. break;  

  165.        }  

  166.    }  

  167. }  

  168. void file_out(int fd, char *data, int len) {  

  169. while (1) {  

  170.        sem_wait(&write_sem);  

  171.        pthread_mutex_lock(&write_mutex);  

  172.        printf("data_out..........\n");  

  173. if (write(fd, data, len) == -1) {  

  174.            printf("write error! \n");  

  175.        }  

  176.        printf("data_out..........complete\n");  

  177.        pthread_mutex_unlock(&write_mutex);  

  178. if(result_copy==1){  

  179. break;  

  180.        }  

  181.    }  

  182. }  

  183. /*

  184. * put.c

  185. *

  186. *  Created on: May 14, 2012

  187. *      Author: dell

  188. */

  189. #include "signalmove.h"

  190. void put() {  

  191. int fd = open(filename_out, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);  

  192. if (fd == -1) {  

  193.        printf("open file wrong!\n");  

  194.        exit(0);  

  195.    }  

  196.    file_out(fd, data_t, len);  

  197. }  

  198. /*

  199. * get.c

  200. *

  201. *  Created on: May 14, 2012

  202. *      Author: dell

  203. */

  204. #include "signalmove.h"

  205. void get() {  

  206. int fd = open(filename_in, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);  

  207. if (fd == -1) {  

  208.        printf("open file wrong!\n");  

  209.        exit(0);  

  210.    }  

  211.    file_in(fd, data_s, len);  

  212. }  

  213. /*

  214. * copy.c

  215. *

  216. *  Created on: May 14, 2012

  217. *      Author: dell

  218. *  copy data from S to T

  219. */

  220. #include "signalmove.h"

  221. void copy() {  

  222. while (1) {  

  223.        sem_wait(©_sem);  

  224.        pthread_mutex_lock(&read_mutex);  

  225.        pthread_mutex_lock(&write_mutex);  

  226.        printf("copy..........\n");  

  227.        strcpy(data_t,data_s);  

  228. int i=0;  

  229. for(;i<len;i++){  

  230.            data_s[i]=' ';  

  231.        }  

  232.        printf("copy..........complete\n");  

  233.        pthread_mutex_unlock(&write_mutex);  

  234.        pthread_mutex_unlock(&read_mutex);  

  235.        sem_post(&write_sem);  

  236.        sem_post(&read_sem);  

  237. if (result == 0) {  

  238.            result_copy = 1;  

  239. break;  

  240.        }  

  241.    }  

  242. }