版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
实验二嵌入式Linux多线程通信实验程(thread)是在共享内存空间中并发的多道执行路径,它们共享一个进程的资源,如文件描述和信号处理。P(S):将信号量S的值减1,即S=S-1;如果S>0,则该进程继续执行;否则该进程状态置为阻塞状态,进程PCB排入信号量PCB队列末尾,放弃CPU,等待V操作的执行。V(S):1将信号量S的值加1,即S=S+1;2如果S<0,释放信号量队列中第一个PCB所对应的进程,将进程状态111阻塞态改为就绪态。执行V操作的进程继续执行。#include<stdio.h>#include<unistd.h>#include<pthread.h>#include<semaphore.h>#defineMAXSIZE10intstack[MAXSIZE];intsize=50;intfront=-l,rear=0;seni.tavail,full;//avail表示可用的空缓冲区,full表示已存放产品的缓冲区〃生产者pthread_tprovider,customer,end;voidprovider_fun(void)//full表示已存放产品的缓冲区{inti=l;sleep(5);while(i<=size)〃生产50个产品,需要放入到MAXSIZE个缓冲区中{sem_wait(&avail);//avail信号EP操作,表示将可用的空缓冲区个数减1stack[rear]=i;printf('*producethe%dproduct\nn,stack[rear]);rear=(rear+l)%MAXSIZE;i++;sleep(l);sem_post(&full);//full信号量V操作,表示将存放产品的缓冲区个数加1}pthread_exit(NULL);}〃消费者voidcustomer_fun(void)inti=l;while(i<=size){sem_wait(&full);//fulll信号量P操作,表示将存放产品的缓冲区个数减1front=(front+l)%MAXSIZE;printf(H\tconsumethe%dproduct\n,\stack[front]);stack[front]=0;sleep(2);sem_post(&avail);//avail信号量V操作,表示将可用的空缓冲区个数加1i++;}pthread_exit(NULL);}voidend_fun(void){charch;scanf(,,%c',,&ch);pthread_cancel(provider);pthread_cancel(customer);dpthread_exit(NULL);printf(nexit!\iin);}voidmain(){pthread_tprovider,customer;〃定义生产者线程对象和消费者线程对象sem_init(&avail,O,MAXSIZE);〃将avail信号量初始化为MAXSIZEsemJnit(&full,0,0);〃将full信号量初始化为0pthread_create(&provideF,NULL,(void*)provider_fun,NULL);//创建生产者线程pthread_create(&customer,NULL,(void*)customer_fun,NULL)”/消费者线程pthread_create(&end,NULL,(void兔)end_fun,NULL);pthread」oin(provider,NULL);pthread」oin(customer,NULL);pthread」oin(end,NULL);sem_destroy(&a、ail);sem_destroy(&full);}实验三'嵌入式Linux网络通信实验3、TCP套接字通信步骤服务器端:调用socketQ创建套接字,然后初始化stnictsockaddr_m结构体。调用bind函数()为套接字绑定一个IP地址和一个端II号。
调用listenQ^数使套接字成为监听套接字,侦听指定的端II。调用accept()函数,使服务器处于阻塞状态,等待接受客户端连接请求。一旦建立连接,将产生新的套接字,此时就有两个套接字了,原来的那个套接字还在监听等待指定的端II,而新产生的套接字则准备发送或接受数据。利用sendz,sendto和recv/recvfiom进行数据传输。当然也可以调用write或read.数据传输完毕,关闭套接字。请补充server.c中代码//fbwuqi#include<svs/tvpes.h>#include<svs/socket.h> //包含套接字函数库#iiiclude<stdio.h>#include<netinet/in.h>#include<arpa;inet.h>#include<unistd.h>#include<netinet/in.h>#include<arpa;inet.h>#include<unistd.h>//包含AF.INET相关操作的函数^include<string.h> //bzeio()#defineMAXDATASIZE50mt〃服务器端socket〃服务器端socket描述符变量,用以监听客户端hitseivei_sockfd;的TCP连接stmctsockaddi_iiisenTei_addr;stmctsockaddrmclientaddr;intclient_addi_len;acceptQ中的一个参数chai-bufIMAXDATASIZE];〃服务器端sockaddr_in的数据结构〃用于accept()存放客户端的socket数据结构〃用于返回structsockaddr_iii的长度,作为〃创建一个buf来存放接受的数据intnumbytes;〃用以返回接受到的字节数intnew_sockfd;返回一个新的socket,用这个socket接受数据〃当监听到并接受一个TCP连接时,acceptQseiver.sockfd=sock战(AF_INET,SOCK_STREAM,0);〃创建一个TCP套接字,其中协议族为AF_INET,套接字类型为SOCK_STREAM,第三个参数为0servei_addi.sin_fomily=AF_INET;//servrei_addr.sin_faniily为AF_INETsenrer_addr.siii_addr.s_addr=iiiet_addr(M10.10.58.130n);//senrer_addr.siii_addr.s_addr为服务器端IP地址,需经inet_adck()转化为网络IP字节序senrer_addLsm_pon=htons(1025);//servrei_addr.sin_poil为一个人于1024的端I丨号,需经htoiis()转化为网络字节序bmd(senTer_sockfd.(stRictsockaddr *)&server_addi\sizeof(stnictsockaddi));//将senrei_sockfd绑定到seiver_addr指定的IP和端II上listen(serv“_sockfd,5);将其设置为监听套接字〃为servei_sockfd创建包含5个TCP连接的监听队歹listen(serv“_sockfd,5);将其设置为监听套接字wlule(1){client_addi_len=sizeof(sti-uctsockaddi_in);//计算sockaddi_iii的长度new_sockfd=accept(senrer_sockfd,(stnictsockaddr*)&client_addi;&ni】mbytes);〃等待接受客户端发来的TCP连接,若连接成功,返回新的socketnumbytes=recv(new_sockfd,buf,20,0);〃将客户端发来的数据存放在buf中,返回接
受到的字节数if(numbytes){prmtf(n%s\ir\buf);//输出buf中数据}sleep⑶;send(new_sockfd/Iamserver*,20.0); 〃向客户端发送TamseiveiMclose(new_sockfd);if(8==getchar()){break;}}close(seiver_sockfd);leturn0;}客户端:调用socket()创建套接字,然后初始化structsockaddr_m结构体,注意服务器端和客户端的structsockaddr_m结构体应该一致。调用coimectionQ函数与服务器建立连接。利用send/sendto和recv/recvfiom进行数据传输.当然也可以调用write或read.数据传输完毕,关闭套接字。请补充client.c中代码#include<svs/tvpes.h>#include<svs/tvpes.h>#include<svs/socket.h>#include<stdio.h>#include<netmet*m.h>#include<arpa;inet.h>#include<unistd.h>#include<string.h>//包含套接字函数库//包含AF_INET相关结构//包含AF.INET相关操作的函数//bzero()^defineMAXDATASIZE50iiit argc,char*argv[])iiitsockfd,result;//客户端socket描述符变量stmctsockaddi_iiisenTei_addr;//与服务器端sockaddi_iii的数据结构一致chai-buftMAXDATASIZE];〃用以接受服务器端发送过来的数据mtnumbytes;〃用以返回从服务端发送过来的数据字节数sockfd=sock筑(AF_INET$OCK_STREAK0);〃创建一个TCP套接字,其中协议族为AF_INET、套接字类型为SOCK_STREAM.第三个参数为0seiver^addr.siii.fanuly=AF_INET;//addiess_addr_addr.sm_family为AF_INETsenrer_addi.siii_addr.s_addi = met_addi(M10.10.58.130M);//address_addi_addf.siii_addi-.s_addr为服务器端IP地址,需经met_addr()转化为网络IP字节序senrer_addr.siii_pon=htons(1025);//addiess_addi_addr.sin_port为一个人于1024的端丨I号,需经htons()转化为网络字节序result=conn亡ct(sockfd,(structsockaddi*)&seiver_addi\sizeof(stRictsockaddi));//与address_addi_addf指定的服务器建立连接send(sockfd,Mthisisclient”,20,0);//向服务器端发送”thisisclient*'sleep⑶;numbytes=recv(sockfd.buf,50,0);〃接受服务器端发送过来的数据,保存在buf中if(numbvtes){pi-rntfC"%s\ir\buf);//输出buf里面的数据}close(sockfd);leturn0;}实验四、嵌入式Linux串行端口编程实验什么是全双工和半双工全双工(Fullduplex)是说计算机可以同时接受和发送数据——也就是它有两个分开的数据传输通道(一个传入,一个传出)。半双工(Halfduplex)表示计算机不能同时接受和发送数据,而在某一时刻它只能单一的传送或者接收。这通常意味着,它只有一个数据通道。半双工并不是说RS-232的某些信号不能使用,而是,它通常是使用了有别于RS-232的其他不支持全双工的标准。#iiiclude<stdio.h>/*标准输入输出定义*/include<stdlib.h>/*标准函数库定义*/#iiiclude<uiiistd.h>/*Unix标准函数定义*/iiiclude<sys/types.h>iiiclude<sy&/stat.h>include<fcntl.h>/*文件控制定义*/#iiiclude<terniios.h>/*PPSIX终端控制定义*/iiiclude<enno.h>/*错误号定义*/#defineFALSE-1^defineTRUE0mtspeed_an[]={B38400,Bl9200,B9600.B4800,B2400,B1200.B300,B38400.B19200.B9600,B4800.B2400,B1200,E300,};mtname_an[]={38400, 19200,9600,4800.2400, 1200, 300、38400. 19200,9600,4800,2400.1200,300,};charbuff珥1024];iiitLength;//intnByt亡=wiite(fd,buffer’Length);〃读取串口数据代码:dcharbuff[1024];iiitLen;voidset_speed(iiitfd,iiitspeed){inti;intstatus;stmctterniiosOpt;tcgetattr(fd,&Opt);for(i=0:i<sizeof(speed_air)/sizeof(int);i++){if(speed=name_an[i]){tcflush(fd,TCIOFLUSH);cfsetispeed(&Op「speed_an[i]);cfsetospeed(&Opt、speed_an[i]);status=tcsetattr(fd.TCSANOW.&Opt);if(status!=0){perror(HtcsetattrfdlH);return;}tcflush(fd.TCIOFLUSH);mtset_Parity(intfd.iiitdatabits.mtstopbits.mtparity)stmctterniiosoptions;if(tcgetattr(fcl&options)!=0){perior(nSetupSerial1H);retuni(FALSE);}options.c_cflag&=〜CSIZE;switch(databits)/*设置数据位数*/case7:options.c_cflag|=CS7;break;case8:options.c_cflag|=CSS;break;default:fprmtf(stden\HUnsuppoiteddatasize\nM);return(FALSE);}switch(parity)
casen:caseN:options.c_cflag&=~PARENE; /*Clearparityenable*/options.c_iflag&=~INPCK; /*Enableparitychecking*/break;caseV:case'O:options.c.cflag|=(PARODD|PARENB);/*设置为奇效验勺options.c_iflag|=INPCK; /*Disnableparitychecking*/break;case*er:/*Enableparity*//*/*Enableparity*//*转换为偶效验*//*Disnableparitychecknig*/options.c_cflag|=PARENB;options.c_cflag&=~PARODD;options.c_iflag|=INPCK;break;case’s:case's1:/*asnoparity*/options.c_cflag&=~PARENE;options.c.cflag&=-CSTOPB;break;default:fprmtf(stden\”UnsupportedparityuiH);return(FALSE);}/*设置停止位*/switch(stopbits)fcase1:options.c_cflag&=〜CSTOPE;break;case2:options.c_cflag|=CSTOPB;break;default:fprmtf(stden\nUnsuppoitedstopbits®”);return(FALSE);}/*Setmputparityoption*/if(parity!=fnf)options.c_iflag|=INPCK;tcflush(蝕TCIFLUSH);options.c_cc[VTEvIE]=150;/*设置超时15seconds*/options.c_cc[V\nN]=0:/*UpdatetheoptionsanddoitNOW*/if(tcsetatti(fd,TCSANOW,&optious)!=0){penorC'SetupSerial3H);return(FALSE);}retuin(TRUE);}iiitOpeiiDev(chai*Dev){mtfd=open(Dev,O_RDWR); //|O.NOCTTY|O_NDELAYif(-l=fd){penor(HCairtOpenSerialPort”);return-1;}elsereturnfd;}iiit aigc,chai**arg\-){mtfd;intmead;clwbuff{1024];chai-*dev=n/dev/ttvUSB0H;〃串II二fd=OpeiiDev(dev);set_speed(fdjl5200);if(set_Paiity(fd58,l,N)==FALSE){prmtf<nSetParityEnor\nM);exit(0);}while(1)//循坏读取数据{memset(buflF,0,1024);while((nread=read(fd,buff.1024))>0){//printf(M\nLen%d\nHaiiead);bufftnread+1]=SO:buff);memset(buff.0,1024);}}close(fd);exit(0);}实验五、嵌入式Linux内核编程实验你可以使用头文件linux/fs.h中的函数registei_cludev来实现注册一个某个驱动模块对应的主设备号。registei_cludev一般在intdevice_niitQ函数中调用,即将内核驱动模块加载入内核意味着要向内核注册自己。如果你向函数registei_cludev传递为0的主设备号,那么返回的就是动态分配的主设备号。此时应该通过命令“cat/proc/devices”命令输出得到,使用mknod统调用建立设备文件。Linux的驱动程序编译方法将其源代码添加到内核源文件中,然后静态编译整个内核,再运行新的内核来测试编译为模块的形式,单独加载运行调试驱动程序与应用程序的区别应用程序一般有一个main函数,从头到尾执行一个任务;驱动程序却不同,它没有main函数,通过使用宏module_init(初始化函数名);将初始化函数加入内核全局初始化函数列表中,在内核初始化时执行驱动的初始化函数,从而完成驱动的初始化和注册,之后驱动便停止等待被应用软件调用。驱动程序中有一个宏moudule_exit(^出处理函数名)注册退出处理函数。它在驱动退出时被调用。应用程序可以和GLIBC库连接,因此可以包含标准的头文件,比如<stdio.hxstdhb.h>,在驱动程序中是不能使用标准C库的,因此不能调用所有的C库函数,比如输出打印函数只能使用内核的pimtk函数,包含的头文件只能是内核的头文件,比如:<lmuxy'module.h>。字符驱动程序编写流程包含字符设备驱动程序所必需包含的头文件定义字符设备文件名、主设备号或由系统动态分配设备号编写file_operatioiis结构体中功能接丨I函数,如以上device_read、device_\vrite.device_open定义file_opeiations结构变量,建立用户程序调用函数与驱动功能接II的对应关系。编写字符设备驱动程序加载函数,完成设备文件注册及必要的初始化编写字符设备驱动程序卸载函数,完成注销及必要的环境恢复。编写Makefile文件,使用make来编译Makefile,生成****.ko内核模块文件使用“insmod***.ko”加载设备驱动程序,并调用dmesg来查看输出结呆使用“cat/pioc/devicesv查看获取主设备号使用“mknod/dev/设备文件名主设备号0”来创建设备文件编写用户应用程序,调用用户调用接II对驱动功能接II进行测试。使用“rmmod/dev/设备文件名”卸载驱动模块,并调用dmesg查看#include<linux'fs.h>#include<linux-cdev.h>#include<asnruaccess.h>〃文件系统相关的函数和头文件#include<linux'fs.h>#include<linux-cdev.h>#include<asnruaccess.h>#defineDEVICE_NAMEmtDEVICE.MAJOR=0;MDev_fiaiiieM〃定义模块名,用"cat/pioc/devicesv命令查看〃如果为0,则由系统自动分配主设备号#defineM_LENGTH10charcore_dataO[M-LENGTH][M.LENGTH];〃定义内核数据矩阵charcore.data1[M_LENGTH][M_LENGTH];//hitdevice_open(stmctinode*inode,structfile*filp){charc-ar;mti,j;printk(nuseropendevice.\iiH);for(i=0;i<M_LENGTH;i++){ 〃初始化数据foi(j=Oj<M_LENGTH:j++){core_dataO[i][j]=c+j; 〃初始化内核数据矩阵}}return0:}/* */ssize_tdevice_write(stmctfile*filp.constchar*buffei;size_tcount,loff_t*f_pos){intij;printk(nuserwritedatatodrive匚\1】");〃将用户空间传递过来buffer里面的数据复制到内核空间core_datal数组中copy^fionvuseiXbuffer.core.data1.count);for(i=0;KM_LENGTH:i++){fbr(j=Oj<M_LENGTHj++){piintkC%c"、coie_daUil[i]);//使用printk打印内核空间coie_datal数组中元素}pnntk(n\iiH);}returncount;}/* */ssize_tdevice_read(stmctfile*filp,char*buffer,size_tcount,loff.t*flpos){printk(nuserreaddatafromdrivec\n");copy_to_user(buffer,core_dataO,count)^/将内核空间coie_dataO数组复制到用户空间bufferreturncount;/* */iiitdevice_ioctl(stnictinode*iiiode,stmctfile*file.unsignedintcmd.unsignedlongarg){printk(nuserloctlruning.S”);switch(cmd){case1:prmtk(ncmd=%d.\ir\cmd);break;case2:prmtk(ncmd=%d.\ir\cmd);break;case3:prmtk(ncmd=%d.\ir\cmd);break;case4:prmtk(ncmd=%d.\ir\cmd);break;case5:prmtk(ncmd=%d.\ir\cmd);break;}returncmd;}/* */iiitdevice_release(stiuctmode*iiiode,structfile{printk(ndevicerelease\nH);return0;}/*----device_fops结构定义文件操作函数体之后- -*/structfile_opeiationsdevice_fbps={.owner-THIS_MODULE,.iead=device_iead,//W用户接II函数read与驱动功能函数device_read对应起来.unlocked_ioctl=device_ioctl,〃将用户接I丨函数ioctl与驱动功能函数device_ioctl对应起来.open=device_open,〃将用户接II函数open与驱动功能函数device_open对应起来.write=device_write,〃将用户接II函数write与驱动功能函数device_write对应起来.Telease=device_Telease//将用户接I丨函数release与驱动功能函数device_release对应起来};/* */iiitdevice_uut(void){intret;/*字符驱动程序注册:第1个参数为0(表示由系统自动分配主设备号),第2个参数为设备文件名,第3个参数为stmctfile_opeiations结构体变量指针*/iet=register_cludev(0/Demo_device,\&devic亡_fops);if(ret<0){priiitkCregisterchidevfailure!\n”);〃字符驱动程序注册失败returnret;piiiitk(Hregisterchidevok!\iT');DEVICE_MAJOR=ret;〃将系统分配的主设备号保存}return0;}voiddevice_exit(void){〃字符驱动程序注销,第1个参数为主设备号,第2个参数为设备文件名,umegistei_clndev(0/,Demo_deviceM);printk(numegistercludevok!\iiH);}module_init(device_iiiit); 〃指定insmod-加载时执行device^initmodule_exit(device_exit); //rnunod-卸载时执行执行device_exit实验六、嵌入式LinuxQtGUI使用实验//firstDialog・cpp//#include<QtGui>#include"firstDialog.h”firstDialog::fiistDialog(QWidget*parent):QDialog(paient){liiieEdit_l=newQLineEdit;label_l=newQLabel(H+");lineEdit_2=newQLmeEdit;label_2=newQLabel(',=M);liiieEdit_3=newQLineEdit;suniButton=newQPushButton(MsumH);jianfaButton=newQPushButton(1fjiaiifaM);/*按钮部件大小和字体设置*/suniButton->resize(50,20);suniButton->setFont(QFont(MTimes,\1&QFont::Bold));coiinect(suniButton,SIGNAL(clicked())、this.SLOT(clickhm()));comiect(this.SIGNAL(sunisignal(QStrmg,QStnng)).this,SLOT(sumfun(QStnng,QStimg)));
comiect(jianfiuiButton.SIGNAL(clickedQ),tliis,SLOT(clickfxm()));coiinect(tlus, SIGNAL(sunisignal(QStrmg,QStiing)),SLOT(jianfuii(QString,QStiiiig)));QHBoxLavout*topLayout=newQHBoxLayout;topLayout->addWidget(lineEdit_l);topLayout->addWidget(label_l);topLayout->addWidget(lineEdit_2);topLayout->addWidget(label_2);topLayout->addWidget(lineEdit_3);QHBoxLavout*bottoniLayout=newQHBoxLavout;bottoniLayout->addWidget(suniButton);bottoniLayout->addWidge
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2026年广东省深圳市实验中学八年级英语第7章阅读理解专项训练习题及答案
- 四川省成都市实验小学六年级英语第12单元写作练习题及答案
- 浙江省杭州市第二中学七年级语文第8单元综合测试卷及答案
- 湖南省湘教版初中三年级英语上册第6单元阅读理解专项训练习题及答案
- 海洋与海洋生物间的相互关系
- 犬的心理与训练的关系
- 肺动脉高压患者肺血管疾病的早期检测进展
- 苏教版六年级上册比的意义课件
- 销售技巧培训课程
- 系统集成项目管理工程师考前辅导
- 血透病人皮肤瘙痒的护理
- 2025年大学生微电子与集成电路考试试题及答案
- 磨工技师试题及答案解析
- 华为光芯片机考题库
- 中国人寿保全知识课件
- 2025年银川文化旅游发展集团有限公司招聘笔试参考题库含答案解析
- 高考英语3500词顺序版
- 江苏省中等职业学校学业水平试卷题含答案
- 环卫工人交通安全知识培训课件正式完整版
- 吉利工厂过程质量对标标准手册V4
- 医院应急预案汇编3
评论
0/150
提交评论