嵌入式软件设计概述 (11).ppt

上传人:刘静 文档编号:91506753 上传时间:2023-05-27 格式:PPT 页数:111 大小:1.43MB
返回 下载 相关 举报
嵌入式软件设计概述 (11).ppt_第1页
第1页 / 共111页
嵌入式软件设计概述 (11).ppt_第2页
第2页 / 共111页
点击查看更多>>
资源描述

《嵌入式软件设计概述 (11).ppt》由会员分享,可在线阅读,更多相关《嵌入式软件设计概述 (11).ppt(111页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。

1、无名管道无名管道Linux有多种进程间通信(IPC)方式,如果没有IPC,进程只能通过文件系统互相交换信息。IPC机制机制常用的IPC有如下几种:管道信号量共享内存消息队列管道管道管道分为两种无名管道(pipe):是与内存中的一个索引节点相关联的两个文件描述符,没有名字,不会在文件系统中出现。有名管道(fifo):出现于文件系统当中,遵循先入先出的原则来读取数据。pipe、fifo的名称并非硬性规定管道管道无名管道无名管道管道是半双工,数据只能单向传递管道只能在相关的、有共同祖先的进程之间使用创建无名管道创建无名管道创建管道使用pipe调用,关闭管道使用close调用如果成功建立了管道,则会打

2、开两个文件描述符并把它们的值保存在一个整数数组中。其中,filedes0用于读出数据用于读出数据,filedes1用来写入数据用来写入数据。成功返回0,否则返回-1。#includeint pipe(int filedes2);#include#include#include int main(void)int fd2;/*Array for file descriptors*/if(pipe(fd)0)perror(pipe);exit(EXIT_FAILURE);printf(descriptors are%d,%dn,fd0,fd1);close(fd0);close(fd1);exit

3、(EXIT_SUCCESS);pipe.c例例:无名管道创建无名管道创建#include#include#include int main(void)int fd2;/*Array for file descriptors*/if(pipe(fd)0)perror(pipe);exit(EXIT_FAILURE);printf(descriptors are%d,%dn,fd0,fd1);close(fd0);close(fd1);exit(EXIT_SUCCESS);pipe.c例例:无名管道创建无名管道创建#include#include#include int main(void)int

4、 fd2;/*Array for file descriptors*/if(pipe(fd)0)perror(pipe);exit(EXIT_FAILURE);printf(descriptors are%d,%dn,fd0,fd1);close(fd0);close(fd1);exit(EXIT_SUCCESS);pipe.c例例:无名管道创建无名管道创建读写管道读写管道从管道读出数据和写入数据,只要简单的使用read和write调用即可。read从fd0中读取数据,write向fd1中写入数据。如果父进程向子进程发送数据,则父进程需关闭fd0并向fd1写入数据,子进程需关闭fd1,并从fd

5、0读取数据。反之亦然#include#include#include#include#include#include#include#define BUFSZ PIPE_BUFvoid err_quit(char*msg);int main(int argc,char*argv)int fd2;/*File descriptor array for the pipe*/int fdin;/*Descriptor for input file*/char bufBUFSZ;int pid,len;piperw.c例:例:cat功能的又一实现功能的又一实现void err_quit(char*ms

6、g)perror(msg);exit(EXIT_FAILURE);#include#include#include#include#include#include#include#define BUFSZ PIPE_BUFvoid err_quit(char*msg);int main(int argc,char*argv)int fd2;/*File descriptor array for the pipe*/int fdin;/*Descriptor for input file*/char bufBUFSZ;int pid,len;piperw.c例:例:cat功能的又一实现功能的又一

7、实现/*Create the pipe*/if(pipe(fd)0)err_quit(pipe);/*Fork and close the appropriate descriptors*/if(pid=fork()0)write(STDOUT_FILENO,buf,len);close(fd0);else/*Parent is writer,close the read descriptor*/close(fd0);if(fdin=open(argv1,O_RDONLY)0)perror(open);/*Send something*/write(fd1,123n,4);piperw.c/*

8、Create the pipe*/if(pipe(fd)0)err_quit(pipe);/*Fork and close the appropriate descriptors*/if(pid=fork()0)write(STDOUT_FILENO,buf,len);close(fd0);else/*Parent is writer,close the read descriptor*/close(fd0);if(fdin=open(argv1,O_RDONLY)0)perror(open);/*Send something*/write(fd1,123n,4);piperw.c/*Crea

9、te the pipe*/if(pipe(fd)0)err_quit(pipe);/*Fork and close the appropriate descriptors*/if(pid=fork()0)write(STDOUT_FILENO,buf,len);close(fd0);else/*Parent is writer,close the read descriptor*/close(fd0);if(fdin=open(argv1,O_RDONLY)0)perror(open);/*Send something*/write(fd1,123n,4);piperw.c/*Create t

10、he pipe*/if(pipe(fd)0)err_quit(pipe);/*Fork and close the appropriate descriptors*/if(pid=fork()0)write(STDOUT_FILENO,buf,len);close(fd0);else/*Parent is writer,close the read descriptor*/close(fd0);if(fdin=open(argv1,O_RDONLY)0)write(fd1,buf,len);close(fdin);/*Close the write descriptor*/close(fd1)

11、;/*Reap the exit status*/waitpid(pid,NULL,0);exit(EXIT_SUCCESS);void err_quit(char*msg)perror(msg);exit(EXIT_FAILURE);piperw.celse while(len=read(fdin,buf,BUFSZ)0)write(fd1,buf,len);close(fdin);/*Close the write descriptor*/close(fd1);/*Reap the exit status*/waitpid(pid,NULL,0);exit(EXIT_SUCCESS);vo

12、id err_quit(char*msg)perror(msg);exit(EXIT_FAILURE);piperw.c有名管道有名管道有名管道(FIFO)存在于文件系统中,功能比无名管道强大,可以让无关联的进程交换数据。有名管道创建函数有名管道创建函数有名管道创建函数为mkfifo(与shell命令同名)。执行成功返回0,否则返回-1,并设置errno。#include#include int mkfifo(const char*pathname,mode_t mode)#include#include#include#include#include int main(int argc,ch

13、ar*argv)mode_t mode=0666;if(argc!=2)puts(USAGE:newfifo name);exit(EXIT_FAILURE);if(mkfifo(argv1,mode)0)perror(mkfifo);exit(EXIT_FAILURE);exit(EXIT_SUCCESS);newfifo.c例:有名管道例:有名管道#include#include#include#include#include int main(int argc,char*argv)mode_t mode=0666;if(argc!=2)puts(USAGE:newfifo name);e

14、xit(EXIT_FAILURE);if(mkfifo(argv1,mode)0)perror(mkfifo);exit(EXIT_FAILURE);exit(EXIT_SUCCESS);newfifo.c例:有名管道例:有名管道FIFO操作函数操作函数打开FIFO管道:open关闭FIFO管道:close读取FIFO管道:read写入FIFO管道:write#include#include#include#include#include#include#include#include int main(void)int fd;int len;char bufPIPE_BUF;mode_t m

15、ode=0666;if(mkfifo(fifo1,mode)0)perror(mkfifo);exit(EXIT_FAILURE);if(fd=open(fifo1,O_RDONLY)0)printf(rdfifo read:%s,buf);close(fd);exit(EXIT_SUCCESS);readfifo.c例:有名管道的读程序例:有名管道的读程序#include#include#include#include#include#include#include#include int main(void)int fd;int len;char bufPIPE_BUF;mode_t mo

16、de=0666;if(mkfifo(fifo1,mode)0)perror(mkfifo);exit(EXIT_FAILURE);if(fd=open(fifo1,O_RDONLY)0)printf(rdfifo read:%s,buf);close(fd);exit(EXIT_SUCCESS);readfifo.c例:有名管道的读程序例:有名管道的读程序#include#include#include#include#include#include#include#include int main(void)int fd;int len;char bufPIPE_BUF;mode_t mod

17、e=0666;if(mkfifo(fifo1,mode)0)perror(mkfifo);exit(EXIT_FAILURE);if(fd=open(fifo1,O_RDONLY)0)printf(rdfifo read:%s,buf);close(fd);exit(EXIT_SUCCESS);readfifo.c例:有名管道的读程序例:有名管道的读程序#include#include#include#include#include#include#include#include int main(void)int fd;int len;char bufPIPE_BUF;mode_t mode

18、=0666;if(mkfifo(fifo1,mode)0)perror(mkfifo);exit(EXIT_FAILURE);if(fd=open(fifo1,O_RDONLY)0)printf(rdfifo read:%s,buf);close(fd);exit(EXIT_SUCCESS);readfifo.c例:有名管道的读程序例:有名管道的读程序#include#include#include#include#include#include#include#include int main(void)int fd;int len;char bufPIPE_BUF;mode_t mode=

19、0666;if(mkfifo(fifo1,mode)0)perror(mkfifo);exit(EXIT_FAILURE);if(fd=open(fifo1,O_RDONLY)0)printf(rdfifo read:%s,buf);close(fd);exit(EXIT_SUCCESS);readfifo.c例:有名管道的读程序例:有名管道的读程序#include#include#include#include#include#include#include#include#include int main(void)int fd;/*Descriptor for FIFO*/int len

20、;/*Bytes written to FIFO*/char buf PIPE_BUF;/*Ensure atomic writes*/time_t tp;/*For time call*/printf(I am%dn,getpid();if(fd=open(fifo1,O_WRONLY)0)perror(open);exit(EXIT_FAILURE);例:有名管道的写程序例:有名管道的写程序writefifo.c#include#include#include#include#include#include#include#include#include int main(void)int

21、 fd;/*Descriptor for FIFO*/int len;/*Bytes written to FIFO*/char buf PIPE_BUF;/*Ensure atomic writes*/time_t tp;/*For time call*/printf(I am%dn,getpid();if(fd=open(fifo1,O_WRONLY)0)perror(open);exit(EXIT_FAILURE);例:有名管道的写程序例:有名管道的写程序writefifo.c#include#include#include#include#include#include#include

22、#include#include int main(void)int fd;/*Descriptor for FIFO*/int len;/*Bytes written to FIFO*/char buf PIPE_BUF;/*Ensure atomic writes*/time_t tp;/*For time call*/printf(I am%dn,getpid();if(fd=open(fifo1,O_WRONLY)0)perror(open);exit(EXIT_FAILURE);例:有名管道的写程序例:有名管道的写程序writefifo.c#include#include#inclu

23、de#include#include#include#include#include#include int main(void)int fd;/*Descriptor for FIFO*/int len;/*Bytes written to FIFO*/char buf PIPE_BUF;/*Ensure atomic writes*/time_t tp;/*For time call*/printf(I am%dn,getpid();if(fd=open(fifo1,O_WRONLY)0)perror(open);exit(EXIT_FAILURE);例:有名管道的写程序例:有名管道的写程

24、序writefifo.cwhile(1)time(&tp);len=sprintf(buf,wrfifo%d sends%s,getpid(),ctime(&tp);if(write(fd,buf,len)0)perror(write);close(fd);exit(EXIT_FAILURE);sleep(3);close(fd);exit(EXIT_SUCCESS);writefifo.cwhile(1)time(&tp);/从从1970年年1月月1日起到现在的秒数日起到现在的秒数len=sprintf(buf,wrfifo%d sends%s,getpid(),ctime(&tp);if(

25、write(fd,buf,len)0)perror(write);close(fd);exit(EXIT_FAILURE);sleep(3);close(fd);exit(EXIT_SUCCESS);writefifo.cwhile(1)time(&tp);len=sprintf(buf,wrfifo%d sends%s,getpid(),ctime(&tp);if(write(fd,buf,len)0)perror(write);close(fd);exit(EXIT_FAILURE);sleep(3);close(fd);exit(EXIT_SUCCESS);writefifo.cwhil

26、e(1)time(&tp);len=sprintf(buf,wrfifo%d sends%s,getpid(),ctime(&tp);if(write(fd,buf,len)0)perror(write);close(fd);exit(EXIT_FAILURE);sleep(3);close(fd);exit(EXIT_SUCCESS);writefifo.cwhile(1)time(&tp);len=sprintf(buf,wrfifo%d sends%s,getpid(),ctime(&tp);if(write(fd,buf,len)0)perror(write);close(fd);ex

27、it(EXIT_FAILURE);sleep(3);close(fd);exit(EXIT_SUCCESS);writefifo.c为了防止出现多个程序同时访问一个共享资源而引发的问题,需要采取一种机制,使得在任一时刻,只有一个进程可以访问到临界区域,即信号量机制信号量分类二进制信号量(二元信号量):取值为0、1通用信号量:取值可为0或任意正整数。信号量信号量P操作:如果信号量的值大于0,就给它减1;如果信号量的值等于0,就挂起该进程的执行。PV操作操作V操作:如果有其他进程因等待信号量而被挂起,就让它恢复运行;如果没有进程因等待信号量而挂起,就给它加1。对普通变量进行加减是不行的,因为在c/

28、c+等语言中,没有一个原子操作可以完成变量检测和加减的功能。以下几个函数用于处理信号量操作#include#include#include int semget(key_t key,int num_sems,int sem_flags);int semop(int sem_id,struct sembuf*sem_ops,size_t num_sem_ops);int semctl(int sem_id,int sem_num,int command,);信号量处理函数信号量处理函数该函数的作用是创建一个新信号量,或取得一个已有信号量。key:整数值。不相关的进程可以通过它来访问同一个信号量不

29、相关的进程可以通过它来访问同一个信号量。程序对信号量的访问都是间接的,它先提供一个键,再由系统生成一个信号量标识符,其他进程都通过semget函数返回信号量标识符。int semget(key_t key,int num_sems,int sem_flags);semget函数函数该函数的作用是创建一个新信号量,或取得一个已有信号量。num_semsnum_sems:整数值。需要的信号量数目,一般总是1.sem_flagssem_flags:一组标志,代表该信号量的权限。IPC_CREAT表示创建一个新的信号量(即使对应键已经创建了信号量,也不会错误),可以和权限位按位或。int semget

30、(key_t key,int num_sems,int sem_flags);semget函数函数int semop(int sem_id,struct sem_buf*sem_ops,size_t num_sem_ops);该函数的作用是改变信号量的值sem_idsem_id:由semget返回的信号量标识符。sem_opssem_ops:指向一个结构数组的指针,该结构描述了信号量操作情况num_sem_opsnum_sem_ops:上述结构数组中元素的个数。semop函数函数int semop(int sem_id,struct sem_buf*sem_ops,size_t num_sem

31、_ops);该函数的作用是改变信号量的值sem_idsem_id:由semget返回的信号量标识符。sem_opssem_ops:指向一个结构数组的指针,该结构描述了信号量操作情况num_sem_opsnum_sem_ops:上述结构数组中元素的个数。struct sembufshort sem_num;/信号量编号,如果不使用一组信号量,则取 值一般为0short sem_op;/一次操作中希望改变的值,可以为-1,即P 操作,也可以为1,即V操作short sem_flg;/通常设为SEM_UNDO,指示操作系统将跟踪当前进程对这个信号量的修改情况,如果这个进程没有释放信号量即终止,那么操

32、作系统将自动释放该进程持有的信号量。semop函数函数该函数允许直接控制信号量信息。sem_idsem_id:信号量标识符sem_numsem_num:信号量编号,如果只有一个信号量,取值为mandcommand:SETVAL:信号量初始化的标识。IPC_RMID:删除不再使用的信号量。int semctl(int sem_id,int sem_num,int command,);semctl函数函数该函数允许直接控制信号量信息。如果存在第四个参数,将会是一个unionsemun结构。这个需要程序这个需要程序员自己定义员自己定义。union semunint val,/信号量初始值信号量初始值

33、struct semid_ds*buf;unsigned short*arrayint semctl(int sem_id,int sem_num,int command,);semctl函数函数用两个不同字符的输出代表进入和离开缓冲区。如果程序启动时带有一个参数,它将在进入和退出临界区域时打印字符X,而程序的其他运行实例将在进入和退出临界区域时打印字符O。因为在任意给定时刻,只有一个进程能进入临界区域,因此字符X和O都应成对出现。信号量使用举例信号量使用举例#include#include#include#include#include#include union semun int val

34、;struct semid_ds*buf;unsigned short int*array;struct seminfo*_buf;设置semctl函数要用的联合体类型sem.cstatic int set_semvalue(void);static void del_semvalue(void);static int semaphore_p(void);static int semaphore_v(void);static int sem_id;int main(int argc,char*argv)int i;int pause_time;char op_char=O;srand(unsi

35、gned int)getpid();sem_id=semget(key_t)1234,1,0666|IPC_CREAT);函数声明、信号量定义sem.cstatic int set_semvalue(void);static void del_semvalue(void);static int semaphore_p(void);static int semaphore_v(void);static int sem_id;int main(int argc,char*argv)int i;int pause_time;char op_char=O;srand(unsigned int)getp

36、id();sem_id=semget(key_t)1234,1,0666|IPC_CREAT);变量初值、随机种子sem.cstatic int set_semvalue(void);static void del_semvalue(void);static int semaphore_p(void);static int semaphore_v(void);static int sem_id;int main(int argc,char*argv)int i;int pause_time;char op_char=O;srand(unsigned int)getpid();sem_id=se

37、mget(key_t)1234,1,0666|IPC_CREAT);创建一个信号量sem.cif(argc 1)if(!set_semvalue()fprintf(stderr,Failed to initialize semaphoren);exit(EXIT_FAILURE);op_char=X;sleep(5);如果有参数,设置信号量设置信号量,修改字符变量为X,睡眠5秒static int set_semvalue(void)union semun sem_union;sem_union.val=1;/信号量初值为1if(semctl(sem_id,0,SETVAL,sem_union

38、)=-1)return(0);return(1);将信号量值初始化为1sem.cfor(i=0;i 1)sleep(10);del_semvalue();exit(EXIT_SUCCESS);/主函数结束static int set_semvalue(void)union semun sem_union;sem_union.val=1;if(semctl(sem_id,0,SETVAL,sem_union)=-1)return(0);return(1);第一第一个进程睡眠个进程睡眠10秒,删除信秒,删除信号量,程序结束号量,程序结束static void del_semvalue(void)u

39、nion semun sem_union;if(semctl(sem_id,0,IPC_RMID,sem_union)=-1)fprintf(stderr,Failed to delete semaphoren);sem.cif(argc 1)sleep(10);del_semvalue();exit(EXIT_SUCCESS);/主函数结束static int set_semvalue(void)union semun sem_union;sem_union.val=1;if(semctl(sem_id,0,SETVAL,sem_union)=-1)return(0);return(1);初

40、始化信号量初始化信号量sem.cstatic void del_semvalue(void)union semun sem_union;if(semctl(sem_id,0,IPC_RMID,sem_union)=-1)fprintf(stderr,Failed to delete semaphoren);static int semaphore_p(void)struct sembuf sem_b;sem_b.sem_num=0;sem_b.sem_op=-1;sem_b.sem_flg=SEM_UNDO;删除信号量删除信号量sem.cstatic void del_semvalue(voi

41、d)union semun sem_union;if(semctl(sem_id,0,IPC_RMID,sem_union)=-1)fprintf(stderr,Failed to delete semaphoren);static int semaphore_p(void)struct sembuf sem_b;sem_b.sem_num=0;sem_b.sem_op=-1;sem_b.sem_flg=SEM_UNDOP操作操作sem.cif(semop(sem_id,&sem_b,1)=-1)fprintf(stderr,semaphore_p failedn);return(0);ret

42、urn(1);static int semaphore_v(void)struct sembuf sem_b;sem_b.sem_num=0;sem_b.sem_op=1;sem_b.sem_flg=SEM_UNDO;if(semop(sem_id,&sem_b,1)=-1)fprintf(stderr,semaphore_v failedn);return(0);return(1);P操作操作sem.cif(semop(sem_id,&sem_b,1)=-1)fprintf(stderr,semaphore_p failedn);return(0);return(1);static int

43、semaphore_v(void)struct sembuf sem_b;sem_b.sem_num=0;sem_b.sem_op=1;sem_b.sem_flg=SEM_UNDO;if(semop(sem_id,&sem_b,1)=-1)fprintf(stderr,semaphore_v failedn);return(0);return(1);V操作操作sem.c共享内存是IPC通信的另一种方法,它允许两个不相关的进程访问同一个逻辑内存。共享内存是在两个正在运行的进程间传递数据的一种非常有效的方式。共享内存并未提供同步机制,所以需要用其他机制来同步对共享内存的访问,这将由程序员来负责。共

44、享内存简介共享内存简介共享内存是由IPC为进程创建的一个特殊的地址范围,出现在该进程的地址空间中,其他进程可以将同一段共享内存连接到他们自己的地址空间中。所有进程都可以访问共享内存中的地址,就好像他们是由malloc分配的一样。如果一个进程向共享内存中写了数据,那么其他进程将立刻能够看到。关于关于共享工作原理共享工作原理共享内存示意图共享内存示意图共享内存共享内存进程进程A A的逻辑地址空间的逻辑地址空间进程进程B B的逻辑地址空间的逻辑地址空间物理内存物理内存该函数用来创建共享内存。#include#include#include int shmget(key_t key,size_t si

45、ze,int shmflg);shmget函数函数key:与信号量一样,程序需要提供一个key,以此键值来获取一个有效的共享内存标识符。int shmget(key_t key,size_t size,int shmflg);shmget函数说明函数说明size:要申请的共享内存大小,以字节为单位。shmflg:权限位,与创建文件的mode标志一样,并可与IPC_CREAT相或返回值:创建成功则返回共享内存标识符,失败返回-1.第一次创建共享内存时,它还不能被任何程序使用,必须使用shmat函数将其连接到一个进程的地址空间中。#include#include#include void*shma

46、t(int shm_id,const void*shm_addr,int shmflg);shmat函数函数shm_id:shmget返回的共享内存标识符。void*shmat(int shm_id,const void*shm_addr,int shmflg);shmat函数说明函数说明shm_addr:指定共享内存连接到当前进程中的地址位置,此参数值通常是个空指针,表示让系统来选择共享内存的地址。shmflg:一组标志位,包含例如读写权限等。返回值:如果调用成功,返回指向共享内存第一个字节的指针,如果失败,返回-1.该函数用来将共享内存从当前进程中分离,其参数为shmat返回的地址指针。成

47、功时返回0,失败时返回-1.将共享内存从进程中分离并未删除它,仅使得当前进程不再能使用该共享内存。#include#include#include void*shmdt(const void*shm_addr);shmdt函数函数共享内存控制函数。#include#include#include int shmctl(int shm_id,int command,struct shmid_ds*buf);shmctl函数函数shm_id:shmget返回的共享内存标识符。int shmctl(int shm_id,int command,struct shmid_ds*buf);shmctl函

48、数说明函数说明返回值:成功返回0,失败返回-mand:要采取的动作,例如删除共享内存。buf:指向包含共享内存模式和访问权限的结构。编写生产者、消费者程序。第一个程序(消费者)创建一个共享内存段,并将其中的内容显示出来。第二个程序(生产者)连接到一个已有的共享内存段,并允许我们向其中写入数据。定义数据结构(share.h)#define TEXT_SZ 2048/申请共享内存大小struct shared_use_st int written_by_you;char some_textTEXT_SZ;举例举例#include#include#include#include#include#in

49、clude#include#include share.hint main()int running=1;void*shared_memory=(void*)0;struct shared_use_st*shared_stuff;int shmid;srand(unsigned int)getpid();shmid=shmget(key_t)1234,sizeof(struct shared_use_st),0666|IPC_CREAT);if(shmid=-1)fprintf(stderr,shmget failedn);exit(EXIT_FAILURE);#define TEXT_SZ

50、2048struct shared_use_st int written_by_you;char some_textTEXT_SZ;例:例:消费者程序消费者程序customer.c#include#include#include#include#include#include#include#include share.hint main()int running=1;void*shared_memory=(void*)0;struct shared_use_st*shared_stuff;int shmid;srand(unsigned int)getpid();shmid=shmget(k

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 教育专区 > 大学资料

本站为文档C TO C交易模式,本站只提供存储空间、用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。本站仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知淘文阁网,我们立即给予删除!客服QQ:136780468 微信:18945177775 电话:18904686070

工信部备案号:黑ICP备15003705号© 2020-2023 www.taowenge.com 淘文阁