




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、精选优质文档-倾情为你奉上实验二 嵌入式 Linux 多线程通信实验程( thread)是在共享内存空间中并发的多道执行路径,它们共享一个进程的资源,如文件描述和信号处理。P( S): 将信号量 S 的值减 1,即 S=S-1; 如果 S0,则该进程继续执行;否则该进程状态置为阻塞状态,进程 PCB 排入信号量PCB 队列末尾,放弃 CPU,等待 V 操作的执行。V( S):1 将信号量 S 的值加 1,即 S=S+1;2 如果 S0,释放信号量队列中第一个 PCB 所对应的进程,将进程状态由阻塞态改为就绪态。执行 V 操作的进程继续执行。#include <stdio.h>#in
2、clude <unistd.h>#include <pthread.h>#include <semaphore.h>#define MAXSIZE 10int stackMAXSIZE;int size=50;int front=-1,rear=0;sem_t avail,full; /avail 表示可用的空缓冲区,full 表示已存放产品的缓冲区/生产者pthread_t provider,customer,end;void provider_fun(void) /full 表示已存放产品的缓冲区int i=1;sleep(5);while(i<=
3、size) /生产50 个产品,需要放入到MAXSIZE 个缓冲区中sem_wait(&avail); /avail 信号量P 操作,表示将可用的空缓冲区个数减1stackrear=i;printf("produce the %d productn",stackrear);rear=(rear+1)%MAXSIZE;i+;sleep(1);sem_post(&full); /full 信号量V 操作,表示将存放产品的缓冲区个数加1pthread_exit(NULL);/消费者void customer_fun(void)int i=1;while(i<
4、=size)sem_wait(&full); /fulll 信号量P 操作,表示将存放产品的缓冲区个数减1front=(front+1)%MAXSIZE;printf("t consume the%d productn",stackfront);stackfront=0;sleep(2);sem_post(&avail); /avail 信号量V 操作,表示将可用的空缓冲区个数加1i+;pthread_exit(NULL);void end_fun(void)char ch; scanf("%c",&ch); pthread_ca
5、ncel(provider); pthread_cancel(customer);d pthread_exit(NULL); printf("exit!n");void main()pthread_t provider,customer; /定义生产者线程对象和消费者线程对象sem_init(&avail,0,MAXSIZE); /将avail 信号量初始化为MAXSIZEsem_init(&full,0,0); /将full 信号量初始化为0 pthread_create(&provider, NULL, (void *)provider_fun,
6、 NULL); / 创建生产者线程 pthread_create(&customer, NULL, (void *)customer_fun, NULL);/ 消费者线程 pthread_create(&end, NULL, (void *)end_fun, NULL);pthread_join(provider,NULL);pthread_join(customer,NULL);pthread_join(end,NULL);sem_destroy(&avail);sem_destroy(&full);实验三、嵌入式 Linux 网络通信实验3、TCP套接字通信
7、步骤服务器端:(1)调用socket()创建套接字,然后初始化struct sockaddr_in结构体。(2)调用bind函数()为套接字绑定一个IP地址和一个端口号。(3)调用listen()函数使套接字成为监听套接字,侦听指定的端口。(4)调用accept()函数,使服务器处于阻塞状态,等待接受客户端连接请求。一旦建立连接,将产生新的套接字,此时就有两个套接字了,原来的那个套接字还在监听等待指定的端口,而新产生的套接字则准备发送或接受数据。(5)利用send/sendto和recv/recvfrom进行数据传输。当然也可以调用write或read.(6)数据传输完毕,关闭套接字。请补充s
8、erver.c中代码/fuwuqi#include <sys/types.h> #include <sys/socket.h>/ 包含套接字函数库 #include <stdio.h> #include <netinet/in.h> / 包含AF_INET相关结构 #include <arpa/inet.h> / 包含AF_INET相关操作的函数 #include <unistd.h> #include <string.h> /bzero()#define MAXDATASIZE 50int main() in
9、t server_sockfd; /服务器端socket描述符变量,用以监听客户端的TCP连接int new_sockfd ; /当监听到并接受一个TCP连接时,accept()返回一个新的socket,用这个socket接受数据struct sockaddr_in server_addr; /服务器端sockaddr_in的数据结构struct sockaddr_in client_addr; /用于accept()存放客户端的socket数据结构int client_addr_len; /用于返回struct sockaddr_in的长度,作为accept()中的一个参数char bufM
10、AXDATASIZE; /创建一个buf来存放接受的数据int numbytes; /用以返回接受到的字节数 server_sockfd = socket(AF_INET , SOCK_STREAM , 0); /创建一个TCP套接字,其中协议族为AF_INET,套接字类型为SOCK_STREAM,第三个参数为0server_addr.sin_family = AF_INET; /server_addr.sin_family为AF_INET server_addr.sin_addr.s_addr = inet_addr("10.10.58.130"); /server_ad
11、dr.sin_addr.s_addr为服务器端IP地址,需经inet_addr()转化为网络IP字节序 server_addr.sin_port =htons(1025); /server_addr.sin_port为一个大于1024的端口号,需经htons()转化为网络字节序 bind(server_sockfd,(struct sockaddr *)&server_addr,sizeof(struct sockaddr); /将server_sockfd绑定到server_addr指定的IP和端口上 listen(server_sockfd,5); /为server_sockfd创
12、建包含5个TCP连接的监听队列,将其设置为监听套接字 while (1) client_addr_len = sizeof(struct sockaddr_in); /计算sockaddr_in的长度 new_sockfd= accept(server_sockfd,(struct sockaddr *)&client_addr,&numbytes);/等待接受客户端发来的TCP连接,若连接成功,返回新的socket numbytes = recv(new_sockfd,buf,20, 0); /将客户端发来的数据存放在buf中,返回接受到的字节数 if (numbytes)
13、printf(" %s n",buf); /输出buf中数据 sleep(3); send(new_sockfd,"I am server",20, 0); /向客户端发送"I am server" close(new_sockfd);if('8'=getchar() break; close(server_sockfd); return 0; 客户端:(1)调用socket()创建套接字,然后初始化struct sockaddr_in结构体,注意服务器端和客户端的struct sockaddr_in结构体应该一致。(
14、2)调用connection()函数与服务器建立连接。(3)利用send/sendto和recv/recvfrom进行数据传输. 当然也可以调用write或read.(4)数据传输完毕,关闭套接字。 请补充client.c中代码/KEHU#include <sys/types.h> #include <sys/socket.h>/ 包含套接字函数库 #include <stdio.h> #include <netinet/in.h>/ 包含AF_INET相关结构 #include <arpa/inet.h>/ 包含AF_INET相关操
15、作的函数 #include <unistd.h> #include <string.h> /bzero()#define MAXDATASIZE 50int main(int argc, char *argv) int sockfd,result; /客户端socket描述符变量struct sockaddr_in server_addr;/与服务器端sockaddr_in的数据结构一致char bufMAXDATASIZE; /用以接受服务器端发送过来的数据 int numbytes; /用以返回从服务端发送过来的数据字节数 sockfd = socket(AF_IN
16、ET,SOCK_STREAM, 0); /创建一个TCP套接字,其中协议族为AF_INET,套接字类型为SOCK_STREAM,第三个参数为0 server_addr.sin_family =AF_INET;/address_addr_addr.sin_family为AF_INET server_addr.sin_addr.s_addr = inet_addr("10.10.58.130"); /address_addr_addr.sin_addr.s_addr为服务器端IP地址,需经inet_addr()转化为网络IP字节序 server_addr.sin_port =h
17、tons(1025);/address_addr_addr.sin_port为一个大于1024的端口号,需经htons()转化为网络字节序 result = connect(sockfd,(struct sockaddr *)&server_addr,sizeof(struct sockaddr);/与address_addr_addr指定的服务器建立连接 send(sockfd,"this is client",20, 0); /向服务器端发送"this is client"sleep(3); numbytes = recv(sockfd,bu
18、f,50, 0); /接受服务器端发送过来的数据,保存在buf中 if (numbytes) printf(" %s n",buf); /输出buf里面的数据 close(sockfd); return 0;实验四、嵌入式 Linux 串行端口编程实验6. 什么是全双工和半双工全双工(Full duplex)是说计算机可以同时接受和发送数据也就是它有两个分开的数据传输通道(一个传入,一个传出)。半双工(Half duplex)表示计算机不能同时接受和发送数据,而在某一时刻它只能单一的传送或者接收。这通常意味着,它只有一个数据通道。半双工并不是说RS-232的某些信号不能使用
19、,而是,它通常是使用了有别于RS-232的其他不支持全双工的标准。#include<stdio.h>/*标准输入输出定义*/#include<stdlib.h>/*标准函数库定义*/#include<unistd.h>/*Unix 标准函数定义*/#include<sys/types.h>#include<sys/stat.h>#include<fcntl.h>/*文件控制定义*/#include<termios.h>/*PPSIX 终端控制定义*/#include<errno.h>/*错误号定义*
20、/#define FALSE -1#define TRUE 0int speed_arr = B38400, B19200, B9600, B4800, B2400, B1200, B300,B38400, B19200, B9600, B4800, B2400, B1200, B300, ;int name_arr = 38400, 19200, 9600, 4800, 2400, 1200, 300, 38400, 19200, 9600, 4800, 2400, 1200, 300, ;char buffer1024;int Length;/int nByte = write(fd, b
21、uffer ,Length);/读取串口数据代码:dchar buff1024;int Len;void set_speed(int fd, int speed)int i; int status; struct termios Opt;tcgetattr(fd, &Opt); for ( i= 0; i <sizeof(speed_arr) / sizeof(int); i+) if (speed = name_arri) tcflush(fd, TCIOFLUSH); cfsetispeed(&Opt, speed_arri); cfsetospeed(&Op
22、t, speed_arri); status = tcsetattr(fd, TCSANOW, &Opt); if (status != 0) perror("tcsetattr fd1"); return; tcflush(fd,TCIOFLUSH); int set_Parity(int fd,int databits,int stopbits,int parity) struct termios options; if ( tcgetattr( fd,&options) != 0) perror("SetupSerial 1");
23、return(FALSE); options.c_cflag&= CSIZE; switch (databits) /*设置数据位数*/ case 7:options.c_cflag |= CS7; break;case 8: options.c_cflag |= CS8;break; default: fprintf(stderr,"Unsupported data sizen"); return (FALSE); switch (parity) case'n':case'N': options.c_cflag&= PARE
24、NB; /* Clear parity enable */options.c_iflag&= INPCK; /* Enable parity checking */break; case'o': case'O': options.c_cflag |= (PARODD | PARENB); /* 设置为奇效验*/options.c_iflag |= INPCK; /* Disnable parity checking */break; case'e': case'E': options.c_cflag |= PARENB;
25、/* Enable parity */options.c_cflag&= PARODD; /* 转换为偶效验*/options.c_iflag |= INPCK; /* Disnable parity checking */break;case'S': case's': /*as no parity*/options.c_cflag&= PARENB;options.c_cflag&= CSTOPB;break; default: fprintf(stderr,"Unsupported parityn"); retur
26、n (FALSE); /* 设置停止位*/switch (stopbits) case 1: options.c_cflag&= CSTOPB; break; case 2: options.c_cflag |= CSTOPB; break;default: fprintf(stderr,"Unsupported stop bitsn"); return (FALSE); /* Set input parity option */if (parity != 'n') options.c_iflag |= INPCK; tcflush(fd,TCIFL
27、USH);options.c_ccVTIME = 150; /* 设置超时15 seconds*/options.c_ccVMIN = 0; /* Update the options and do it NOW */if (tcsetattr(fd,TCSANOW,&options) != 0) perror("SetupSerial 3"); return (FALSE); return (TRUE); int OpenDev(char *Dev)intfd = open( Dev, O_RDWR ); /| O_NOCTTY | O_NDELAYif (-1
28、= fd) perror("Can't Open Serial Port");return -1;elsereturn fd;int main(int argc, char *argv)int fd;int nread;char buff1024;char *dev = "/dev/ttyUSB0" /串口二fd = OpenDev(dev);set_speed(fd,);if (set_Parity(fd,8,1,'N') = FALSE) printf("Set Parity Errorn");exit (
29、0);while (1) /循环读取数据 memset(buff,0,1024); while(nread = read(fd, buff, 1024)>0) /printf("nLen %dn",nread); buffnread+1 = '0' printf("%s", buff); memset(buff,0,1024); close(fd); exit (0);实验五、嵌入式 Linux 内核编程实验你可以使用头文件 linux/fs.h中的函数register_chrdev来实现注册一个某个驱动模块对应的主设备号。regi
30、ster_chrdev一般在int device_init()函数中调用,即将内核驱动模块加载入内核意味着要向内核注册自己。如果你向函数register_chrdev传递为0的主设备号,那么返回的就是动态分配的主设备号。此时应该通过命令 “cat /proc/devices”命令输出得到,使用mknod统调用建立设备文件。4Linux 的驱动程序编译方法(1)将其源代码添加到内核源文件中,然后静态编译整个内核,再运行新的内核来测试(2)编译为模块的形式,单独加载运行调试5驱动程序与应用程序的区别(1)应用程序一般有一个 main 函数,从头到尾执行一个任务;驱动程序却不同,它没有 main 函
31、数,通过使用宏module_init(初始化函数名); 将初始化函数加入内核全局初始化函数列表中,在内核初始化时执行驱动的初始化函数,从而完成驱动的初始化和注册,之后驱动便停止等待被应用软件调用。驱动程序中有一个宏moudule_exit(退出处理函数名)注册退出处理函数。它在驱动退出时被调用。(2)应用程序可以和 GLIBC 库连接,因此可以包含标准的头文件,比如<stdio.h><stdlib.h>, 在驱动程序中是不能使用标准 C 库的,因此不能调用所有的 C 库函数,比如输出打印函数只能使用内核的 printk函数,包含的头文件只能是内核的头文件,比如: <
32、;linux/module.h>。7字符驱动程序编写流程(1) 包含字符设备驱动程序所必需包含的头文件(2) 定义字符设备文件名、主设备号或由系统动态分配设备号(3) 编写file_operations结构体中功能接口函数,如以上device_read、device_write, device_open(4) 定义file_operations结构变量,建立用户程序调用函数与驱动功能接口的对应关系。(5) 编写字符设备驱动程序加载函数,完成设备文件注册及必要的初始化(6) 编写字符设备驱动程序卸载函数,完成注销及必要的环境恢复。(7) 编写Makefile文件,使用make来编译Make
33、file,生成*.ko内核模块文件(8) 使用“insmod *.ko”加载设备驱动程序,并调用dmesg来查看输出结果(9) 使用“cat /proc/devices” 查看获取主设备号(10) 使用“mknod /dev/设备文件名 主设备号 0”来创建设备文件(11) 编写用户应用程序,调用用户调用接口对驱动功能接口进行测试。(12) 使用“rmmod /dev/设备文件名”卸载驱动模块,并调用dmesg查看#include <linux/module.h> /模块所需的大量符号和函数定义#include <linux/fs.h> /文件系统相关的函数和头文件#i
34、nclude <linux/cdev.h> /cdev结构的头文件#include <asm/uaccess.h> /copy_to_user()/copy_from_user()定义#define DEVICE_NAME "Dev_frame"/定义模块名,用”cat /proc/devices”命令查看int DEVICE_MAJOR = 0; /如果为0,则由系统自动分配主设备号#define M_LENGTH 10char core_data0M_LENGTHM_LENGTH;/定义内核数据矩阵char core_data1M_LENGTHM
35、_LENGTH; /*-*/ int device_open(struct inode *inode, struct file *filp) charc='a'inti,j;printk("user open device.n"); for(i=0;i<M_LENGTH;i+)/初始化数据for(j=0;j<M_LENGTH;j+)core_data0ij=c+j;/初始化内核数据矩阵 return 0; /*-*/ ssize_t device_write(struct file *filp,const char *buffer, size_t
36、 count, loff_t *f_pos) inti,j;printk("user write data to driver.n");/将用户空间传递过来buffer里面的数据复制到内核空间core_data1数组中 copy_from_user(buffer,core_data1,count); for(i=0;i<M_LENGTH;i+)for(j=0;j<M_LENGTH;j+)printk("%c",core_data1i);/使用printk打印内核空间core_data1数组中元素printk("n");re
37、turn count;/*-*/ssize_t device_read(struct file *filp, char *buffer, size_t count, loff_t *f_pos) printk("user read data from driver.n");copy_to_user(buffer,core_data0,count);/将内核空间core_data0数组复制到用户空间buffer return count; /*-*/int device_ioctl(struct inode *inode, struct file *file, unsigne
38、d int cmd, unsigned long arg) printk("user ioctl runing.n");switch(cmd)case 1:printk("cmd = %d.n",cmd);break; case 2: printk("cmd = %d.n",cmd);break;case 3: printk("cmd = %d.n",cmd);break;case 4: printk("cmd = %d.n",cmd);break;case 5:printk("cmd
39、 = %d.n",cmd);break; return cmd; /*-*/ int device_release(struct inode *inode, struct file *filp) printk("device releasen"); return 0; /*- device_fops 结构定义文件操作函数体之后- -*/ struct file_operations device_fops = .owner=THIS_MODULE, .read=device_read,/将用户接口函数read与驱动功能函数device_read对应起来 .unlo
40、cked_ioctl=device_ioctl, /将用户接口函数ioctl与驱动功能函数device_ioctl对应起来 .open=device_open, /将用户接口函数open与驱动功能函数device_open对应起来 .write=device_write,/将用户接口函数write与驱动功能函数device_write对应起来 .release=device_release,/将用户接口函数release与驱动功能函数device_release对应起来;/*-*/ int device_init(void) int ret; /*字符驱动程序注册:第1个参数为0(表示由系统自
41、动分配主设备号),第2个参数为设备文件名,第3个参数为struct file_operations结构体变量指针*/ret=register_chrdev(0,"Demo_device",&device_fops);if(ret<0)printk("register chrdev failure!n");/字符驱动程序注册失败 return ret; elseprintk("register chrdev ok!n");DEVICE_MAJOR=ret;/将系统分配的主设备号保存 return 0; void devic
42、e_exit(void) /字符驱动程序注销,第1个参数为主设备号,第2个参数为设备文件名, unregister_chrdev(0,"Demo_device");printk("unregister chrdev ok!n"); module_init(device_init); /指定insmod-加载时执行device_initmodule_exit(device_exit);/rmmod-卸载时执行执行device_exit实验六、嵌入式 Linux Qt GUI 使用实验/firstDialog.cpp/#include <QtGui&g
43、t;#include "firstDialog.h"firstDialog:firstDialog(QWidget *parent) : QDialog(parent) lineEdit_1 = new QLineEdit; label_1 = new QLabel("+"); lineEdit_2 = new QLineEdit; label_2= new QLabel("=");lineEdit_3 = new QLineEdit; sumButton = new QPushButton("sum");jian
44、faButton = new QPushButton("jianfa"); /*按钮部件大小和字体设置*/ sumButton->resize(50, 20); sumButton->setFont(QFont("Times", 18, QFont:Bold); connect(sumButton, SIGNAL(clicked(), this, SLOT(clickfun();connect(this, SIGNAL(sumsignal(QString,QString), this, SLOT(sumfun(QString,QString)
45、; connect(jianfunButton, SIGNAL(clicked(), this, SLOT(clickfun(); connect(this, SIGNAL(sumsignal(QString,QString), this, SLOT(jianfun(QString,QString); QHBoxLayout *topLayout=new QHBoxLayout; topLayout->addWidget(lineEdit_1); topLayout->addWidget(label_1); topLayout->addWidget(lineEdit_2); topLayout->addWidget(label_2); topLayout->addWidget(lineEdit_3); QHBoxLayout *bottomLayout=new QHBoxLayout; bottomLayout->addW
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 炸鸡店打工员工合同范本
- 液压闸刀转让协议书范本
- 物品转让协议书合同范本
- 特色餐饮服务合同协议书
- 物业管道修理合同协议书
- 香蕉生意转让协议书范本
- 火锅串串店合伙人协议书
- 测绘承包合同协议书范本
- 砌墙抹灰包工合同协议书
- 江苏劳动仲裁协议书范本
- 乐蜗家纺行业竞品调研分析
- 2025年度国家广播电视总局直属事业单位公开招聘310人笔试备考题库及答案解析
- 股东内部持股协议书
- 矿山企业管理规章制度汇编
- 2025年从大模型、智能体到复杂AI应用系统的构建报告-以产业大脑为例-浙江大学(肖俊)
- 2024年陕西农业发展集团有限公司招聘笔试真题
- 2025年酒店职位测试题及答案
- 2025年煤矿顶板的考试题及答案
- 田英章楷书7000常用字一.文件
- 爆破作业风险评估职责
- 2025年贵州林东矿业集团有限责任公司招聘笔试参考题库含答案解析
评论
0/150
提交评论