收藏 分销(赏)

《嵌入式操作系统》实验教学大纲:实验四-Linux进程及文件操作程序设计.doc

上传人:二*** 文档编号:4517472 上传时间:2024-09-26 格式:DOC 页数:13 大小:110KB
下载 相关 举报
《嵌入式操作系统》实验教学大纲:实验四-Linux进程及文件操作程序设计.doc_第1页
第1页 / 共13页
亲,该文档总共13页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述

1、实验四:Linux进程及文件操作程序设计第一部分 Linux下文件控制程序设计一、实验目的 1. 熟悉Linux下文件控制程序设计方法。 2. 掌握利用文件锁实现文件互斥访问程序设计方法。 二、实验设备装有RedHat EnterpriseLinux操作系统的PC机三、实验内容1、预备知识 当多个用户共同使用、操作一个文件时,Linux 通常采用的方法是给文件上锁,来避免共享的资源产生竞争的状态。文件锁包括建议性锁和强制性锁。建议性锁要求每个上锁文件的进程都要检查是否有锁存在,并且尊重已有的锁。在一般情况下,内核和系统都不使用建议性锁。强制性锁是由内核执行的锁,当一个文件被上锁进行写入操作的时

2、候,内核将阻止其他任何文件对其进行读写操作。采用强制性锁对性能的影响很大,每次读写操作都必须检查是否有锁存在。 在Linux 中,实现文件上锁的函数有flock和fcntl,其中flock用于对文件施加建议性锁,而fcntl不仅可以施加建议性锁,还可以施加强制锁。同时,fcntl还能对文件的某一记录进行上锁,也就是记录锁。 记录锁又可分为读取锁和写入锁,其中读取锁又称为共享锁,它能够使多个进程都能在文件的同一部分建立读取锁。而写入锁又称为排斥锁,在任何时刻只能有一个进程在文件的某个部分上建立写入锁。当然,在文件的同一部分不能同时建立读取锁和写入锁。 2、fcntl()函数格式 用于建立记录锁的

3、fcntl函数格式如表7.1所示。 表7.1 fcntl函数语法要点 所需头文件 #include #include #include 函数原型 int fcnt1(int fd,int cmd,struct flock *lock) 函数传入参数 fd 文件描述符 cmd(命令)F_DUPFD:复制文件描述符 F_GETFL:得到open设置的标志 F_SETFL:改变open设置的标志 F_SETLK:设置lock描述的文件锁 F_SETLKW:这是F_SETLK的阻塞版本 F_GETLK:获取上锁状态。 lock 设置锁参数 函数返回值 成功:0 出错:1 这里,lock的结构如下所示:

4、 struct flock short l_type; off_t l_start; short l_whence; off_t l_len; pid_t l_pid; lock结构中每个变量的取值含义如表7.2所示。表7.2 lock结构变量取值 l_type F_RDLCK:读取锁(共享锁) F_WRLCK:写入锁(排斥锁) F_UNLCK:解锁 l_stat 相对位移量(字节) l_whence:相对位移量的起点 SEEK_SET:当前位置为文件的开头,新位置为偏移量的大小。 SEEK_CUR:当前位置为文件指针的位置,新位置为当前位置加上偏移量。 SEEK_END:当前位置为文件的结尾

5、,新位置为文件的大小加上偏移量的大小。 l_len 加锁区域的长度。 说明 为加锁整个文件,通常的方法是将l_start =0,l_whence=SEEK_SET,l_len=0。 3、实验内容 编程实现使用fcntl 函数为文件上锁的程序。首先创建了一个hello文件,之后对其上写入锁,最后释放写入锁。 编程步骤如下: 1)首先对flock结构体的对应位赋予相应的值。 2)接着调用fcntl函数判断文件是否可以上锁,如果可以,则对其上写入锁(F_SETLKW);如果已有锁存在,则打印锁类型及上锁进程号,并为其上阻塞性写文件锁(F_SETLKW)。 四、实验步骤1、新建一个子目录。 cd /h

6、ome mkdir exp5 cd exp5 2、编写实现上述功能的程序代码 编辑上锁子函数:vi lock_set.c 启动vi,然后,按i进入插入状态,并输入源程序。最后,按ESC返回到底行模式,并按:wq存盘退出。 编辑写锁测试主程序:vi write_lock.c启动vi,然后,按i进入插入状态,并输入源程序。最后,按ESC返回到底行模式,并按:wq存盘退出。 3、编译、调试上述程序。 gcc write_lock.c o write_lock 4、在PC机端开启两个终端,并且在两个终端上同时运行该程序,以达到多个进程操作一个文件的效果。 新建第一个终端:桌面点右键选择“新建一个终端”

7、 运行write_lock:./ write_lock (第一个终端对hello文件加写锁) 新建第二个终端:桌面点右键选择“新建一个终端” 运行write_lock:./ write_lock (第二个终端对hello文件加写锁,由于第一个写锁还未退出,所以该写锁被阻塞) 在第一个终端按任意键,进行文件解锁。 观察第二个终端,加锁成功。 5、观察实验结果。 首先在终端一上运行./write_lock,然后新建另一个终端并运行./write_lock,由于第一个终端上已经给文件hello上锁了,所以第二个终端程序不能对文件hello上锁而被阻塞。 在第一个终端上,按任意键,使其释放写文件锁。此

8、时,观察终端二可以发现,终端二上的加锁程序完成了加锁任务。 五、实验程序清单1、实现文件加锁的子程序/* lock_set.c */ int lock_set(int fd, int type) struct flock old_lock, lock; lock.l_whence = SEEK_SET; lock.l_start = 0; lock.l_len = 0; lock.l_type = type; lock.l_pid = -1; /* 判断文件是否可以上锁 */ fcntl(fd, F_GETLK, &lock); if (lock.l_type != F_UNLCK) /* 判

9、断文件不能上锁的原因 */ if (lock.l_type = F_RDLCK) /* 该文件已有读取锁 */ printf(Read lock already set by %dn, lock.l_pid); else if (lock.l_type = F_WRLCK) /* 该文件已有写入锁 */ printf(Write lock already set by %dn, lock.l_pid); /* l_type 可能已被F_GETLK修改过 */ lock.l_type = type; /* 根据不同的type值进行阻塞式上锁或解锁 */ if (fcntl(fd, F_SETLK

10、W, &lock) 0) printf(Lock failed:type = %dn, lock.l_type); return 1; switch(lock.l_type) case F_RDLCK: printf(Read lock set by %dn, getpid(); break; case F_WRLCK: printf(Write lock set by %dn, getpid(); break; case F_UNLCK: printf(Release lock by %dn, getpid(); return 1; break; default: break; /* end

11、 of switch */ return 0; 2、测试用主程序/* write_lock.c */ #include #include #include #include #include #include #include #include lock_set.c int main(void) int fd; /* 首先打开文件 */ fd = open(hello, O_RDWR | O_CREAT, 0644); if(fd 0) printf(Open file errorn); exit(1); /* 给文件上写入锁 */ lock_set(fd, F_WRLCK); getchar

12、(); /* 给文件解锁 */ lock_set(fd, F_UNLCK); getchar(); close(fd); return 0; 第二部分: Linux下的多线程程序设计一、实验目的 1、 通过编写经典的“生产者消费者”问题,进一步熟悉Linux 中多线程编程 2、 掌握用信号量处理线程间的同步互斥的方法。 二、实验设备装有RedHat EnterpriseLinux操作系统的PC机三、实验内容“生产者消费者”问题描述如下: 有一个有限缓冲区和两个线程:生产者和消费者。他们分别把产品放入缓冲区和从缓冲区中拿走产品。生产者在缓冲区满时必须等待,消费者在缓冲区空时必须等待。同时,要求生

13、产者和消费者不能同时访问缓冲区。它们之间的关系如图1所示: 图1 生产者消费者问题描述这里要求用有名管道来模拟有限缓冲区,用信号量来解决生产者消费者问题中的同步和互斥问题。1、信号量的考虑可以使用3个信号量,其中两个信号量avail和full分别用于解决生产者和消费者线程之间的同步问题,mutex是用于这两个线程之间的互斥问题。其中avail初始化为N(有界缓冲区的空单元数),mutex 初始化为1,full初始化为0。2、流程图“生产者消费者”问题的流程流程图如图2所示。3、编写代码实验代码中采用的有界缓冲区拥有3个单元,每个单元为5个字节。为了尽量体现每个信号量的意义,在程序中生产过程和消

14、费过程随机(采取0-5s的随机时间间隔)进行的,而且生产者的速度比消费者的速度平均快两倍左右。生产者一次生产一个产品(向缓冲区中放入“hello”字符串),消费者一次消费一个产品。四、实验步骤1、新建目录存放所设计的程序。cd /homemkdir exp8cd exp82、编写“生产者消费者”问题的程序。输入命令 vi producer-customer.c 启动vi,然后,按i进入插入状态,并输入源程序。最后,按ESC返回到底行模式,并按:wq存盘退出。3、编译、调试上述程序。gcc producer-customer.c o producer-customer lpthread4、新建一

15、个终端:桌面点右键选择“新建一个终端”运行 ./producer-customer5、观察实验结果。图2. “生产者消费者”问题的流程流程图五、参考程序清单/*producer-customer.c*/ #include #include #include #include #include #include #include #include #include #include #define MYFIFO myfifo /* 缓冲区有名管道的名字 */#define BUFFER_SIZE 3 /* 缓冲区的单元数 */#define UNIT_SIZE 5 /* 每个单元的大小 */#d

16、efine RUN_TIME 30 /* 运行时间 */#define DELAY_TIME_LEVELS 5.0 /* 周期的最大值 */int fd;time_t end_time;sem_t mutex, full, avail; /* 三个信号量 */*生产者线程*/void *producer(void *arg)int real_write;int delay_time = 0;while(time(NULL) end_time)delay_time = (int)(rand() * DELAY_TIME_LEVELS/(RAND_MAX) / 2.0) + 1;sleep(del

17、ay_time);/*P操作信号量avail和mutex*/sem_wait(&avail);sem_wait(&mutex);printf(nProducer: delay = %dn, delay_time);/*生产者写入数据*/if (real_write = write(fd, hello, UNIT_SIZE) = -1)if(errno = EAGAIN)printf(The FIFO has not been read yet.Please try latern);elseprintf(Write %d to the FIFOn, real_write); /*V操作信号量fu

18、ll和mutex*/sem_post(&full);sem_post(&mutex);pthread_exit(NULL);/* 消费者线程*/void *customer(void *arg)unsigned char read_bufferUNIT_SIZE;int real_read;int delay_time;while(time(NULL) end_time)delay_time = (int)(rand() * DELAY_TIME_LEVELS/(RAND_MAX) + 1;sleep(delay_time);/*P操作信号量full和mutex*/sem_wait(&full

19、);sem_wait(&mutex);memset(read_buffer, 0, UNIT_SIZE);printf(nCustomer: delay = %dn, delay_time);if (real_read = read(fd, read_buffer, UNIT_SIZE) = -1)if (errno = EAGAIN)printf(No data yetn);printf(Read %s from FIFOn, read_buffer);/*V操作信号量avail和mutex*/sem_post(&avail);sem_post(&mutex);pthread_exit(NU

20、LL);int main()pthread_t thrd_prd_id,thrd_cst_id;pthread_t mon_th_id; int ret;srand(time(NULL);end_time = time(NULL) + RUN_TIME;/*创建有名管道*/if(mkfifo(MYFIFO, 0777)0)&(errno!=EEXIST)printf(Cannot create fifon);return errno;/*打开管道*/fd = open(MYFIFO, O_RDWR);if (fd = -1)printf(Open fifo errorn);return fd;

21、/*初始化互斥信号量为1*/ret = sem_init(&mutex, 0, 1);/*初始化avail信号量为N*/ret += sem_init(&avail, 0, BUFFER_SIZE);/*初始化full信号量为0*/ret += sem_init(&full, 0, 0);if (ret != 0)printf(Any semaphore initialization failedn);return ret;/*创建两个线程*/ret = pthread_create(&thrd_prd_id, NULL, producer, NULL);if (ret != 0)printf

22、(Create producer thread errorn);return ret;ret = pthread_create(&thrd_cst_id, NULL, customer, NULL);if(ret != 0)printf(Create customer thread errorn);return ret;pthread_join(thrd_prd_id, NULL);pthread_join(thrd_cst_id, NULL);close(fd);unlink(MYFIFO);return 0;switch(lock.l_type) case F_RDLCK: printf(

23、Read lock set by %dn, getpid(); break; case F_WRLCK: printf(Write lock set by %dn, getpid(); break; case F_UNLCK: printf(Release lock by %dn, getpid(); return 1; break; default: break; /* end of switch */ return 0; 2、测试用主程序/* write_lock.c */ #include #include #include #include #include #include #include #include lock_set.c int main(void) int fd; /* 首先打开文件 */ fd = open(hello, O_RDWR | O_CREAT, 0644); if(fd 0) printf(Open file errorn); exit(1); /* 给文件上写入锁 */ lock_set(fd, F_WRLCK); getchar(); /* 给文件解锁 */ lock_set(fd, F_UNLCK); getchar(); close(fd); return 0;

展开阅读全文
部分上传会员的收益排行 01、路***(¥15400+),02、曲****(¥15300+),
03、wei****016(¥13200+),04、大***流(¥12600+),
05、Fis****915(¥4200+),06、h****i(¥4100+),
07、Q**(¥3400+),08、自******点(¥2400+),
09、h*****x(¥1400+),10、c****e(¥1100+),
11、be*****ha(¥800+),12、13********8(¥800+)。
相似文档                                   自信AI助手自信AI助手
百度文库年卡

猜你喜欢                                   自信AI导航自信AI导航
搜索标签

当前位置:首页 > 教育专区 > 其他

移动网页_全站_页脚广告1

关于我们      便捷服务       自信AI       AI导航        获赠5币

©2010-2024 宁波自信网络信息技术有限公司  版权所有

客服电话:4008-655-100  投诉/维权电话:4009-655-100

gongan.png浙公网安备33021202000488号   

icp.png浙ICP备2021020529号-1  |  浙B2-20240490  

关注我们 :gzh.png    weibo.png    LOFTER.png 

客服