嵌入式面试题

news2024/11/15 19:55:32

1、写一个程序判断电脑是大端字序还是小端字序(加量不加价)

#include <stdio.h>
#include <arpa/inet.h>
typedef unsigned char byte;
typedef unsigned int word;
int main(int argc, char *argv[])
{
	word val32 = 0x11223344;
	byte val8 = *( (byte*)&val32 );
	if(val8 == 0x44)
	{
		printf("本机是⼩端字节序\n");
		val32 = htonl(val32);
		val8 = *( (byte*)&val32 );
		if(val8 == 0x44)
			printf("字节序没有转换\n");
		else
			printf("转换成功, 现在是⽹络字节序了\n");
	}
	return 0;
}

2、说下select和epoll的区别;

Posix标准必有select,poll和epoll是只有Linux才有的,window只有select。也就是说select的使用范围更广

用select实现服务器端

#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <sys/select.h>
#include <arpa/inet.h>
#include <strings.h>
#include <unistd.h>

typedef struct sockaddr Addr;
typedef struct sockaddr_in Addr_in;
typedef struct Node{
	int fd;
	struct Node *next;
}Node;

#define BACKLOG 5

void Argment(int argc, char *argv[]);
void NodeCreate(Node **p);
void AcceptHandle(int sfd, Node **H);
int ClientHandle(int fd);

int main(int argc, char *argv[])
{
	int ret, sfd, nfd = 0;
	Addr_in saddr;
	fd_set rfds;
	Node *H, *p = NULL;

	Argment(argc, argv);

	NodeCreate(&H);

	sfd = socket(AF_INET, SOCK_STREAM, 0);
	if(sfd < 0)
	{
		perror("socket");
		exit(0);
	}
	/*优化4: 允许绑定地址快速重用 */
	int b_reuse = 1;
	setsockopt (sfd, SOL_SOCKET, SO_REUSEADDR, &b_reuse, sizeof (int));

	saddr.sin_family = AF_INET;
	saddr.sin_port = htons(atoi(argv[2]));
	saddr.sin_addr.s_addr = inet_addr(argv[1]);

	if(bind(sfd, (Addr *)&saddr, sizeof(Addr_in)))
	{
		perror("bind");
		exit(0);
	}

	if(listen(sfd, BACKLOG))
	{
		perror("listen");
		exit(0);
	}

	H->fd =sfd;
	while(1)
	{
		FD_ZERO(&rfds);
		p = H;
		nfd = 0;
		while(p != NULL)
		{
			if(p->fd > nfd)
				nfd = p->fd;
			FD_SET(p->fd, &rfds);
			p = p->next;
		}
		printf("nfd = %d run select...\n", nfd);
		ret =select(nfd+1, &rfds, NULL, NULL, NULL);
		if(!ret)
			continue;
		if(ret < 0)
		{
			perror("select");
			exit(0);
		}
		p = H;
		while(p->next != NULL)
		{
			if(FD_ISSET(p->fd, &rfds))
			{
				if(ClientHandle(p->fd) <= 0)
				{
					close(p->fd);
					Node *q = p->next;
					p->fd = q->fd;
					p->next = q->next;
					free(q);
					continue;
				}
			}
			p = p->next;
		}
		if(FD_ISSET(p->fd, &rfds))
			AcceptHandle(p->fd, &H);
#if 1
		p = H;
		puts("");
		printf("Node:");
		while(p != NULL)
		{
			printf("%d ", p->fd);
			p = p->next;
		}
#endif
		if(H->next == NULL)
			break;
	}
	close(sfd);
	free(H);
	return 0;
}

void Argment(int argc, char *argv[])//错误输出
{
	if(argc != 3)
	{
		fprintf(stderr, "%s [addr] [port]\n", argv[0]);
		exit(0);
	}
}

void NodeCreate(Node **p)//创建节点
{
	*p = malloc(sizeof(Node));
	if(p == NULL)
	{
		perror("malloc");
		exit(0);
	}
	bzero(*p, sizeof(Node));
}

void AcceptHandle(int sfd, Node **H)//Accept句柄
{
	Node *p = NULL;
	Addr_in caddr;
	socklen_t caddr_len = sizeof(Addr_in);
	int cfd = accept(sfd, (Addr *)&caddr, &caddr_len);
	if(cfd < 0)
	{
		perror("accept");
		exit(0);
	}
	fprintf(stderr, "client %s:%d connect success.\n",
			inet_ntoa(caddr.sin_addr), ntohs(caddr.sin_port));
	NodeCreate(&p);
	p->fd = cfd;
	p->next = *H;
	*H = p;
}

int ClientHandle(int fd)//客户端句柄
{
	int ret;
	char buf[1024] = {};
	ret = recv(fd, buf, 1024, 0);
	if(ret <= 0)
		return 0;
	printf("fd=%d buf = %s\n",fd, buf);
	if(buf[0] == 'q' && buf[1] == 'u' && buf[2] == 'i' && buf[3] == 't')
		return 0;
	return ret;
}

用select实现客户端

/*./client serv_ip serv_port */
#include "net.h"

void usage (char *s)
{
	printf ("\n%s serv_ip serv_port", s);
	printf ("\n\t serv_ip: server ip address");
	printf ("\n\t serv_port: server port(>5000)\n\n");
}

int main (int argc, char **argv)
{
	int fd = -1;

	int port = -1;
	struct sockaddr_in sin;

	if (argc != 3) {
		usage (argv[0]);
		exit (1);
	}
	/* 1. 创建socket fd */
	if ((fd = socket (AF_INET, SOCK_STREAM, 0)) < 0) {
		perror ("socket");
		exit (1);
	}

	port = atoi (argv[2]);
	if (port < 5000) {
		usage (argv[0]);
		exit (1);
	}
	/*2.连接服务器 */

	/*2.1 填充struct sockaddr_in结构体变量 */
	bzero (&sin, sizeof (sin));

	sin.sin_family = AF_INET;
	sin.sin_port = htons (port);	//网络字节序的端口号
#if 0
	sin.sin_addr.s_addr = inet_addr (SERV_IP_ADDR);
#else
	if (inet_pton (AF_INET, argv[1], (void *) &sin.sin_addr) != 1) {
		perror ("inet_pton");
		exit (1);
	}
#endif

	if (connect (fd, (struct sockaddr *) &sin, sizeof (sin)) < 0) {
		perror ("connect");
		exit (1);
	}

	printf ("Client staring...OK!\n");

	int ret = -1;
	fd_set rset;
	int maxfd = -1;
	struct timeval tout;
	char buf[BUFSIZ];

	while (1) {
		FD_ZERO (&rset);
		FD_SET (0, &rset);
		FD_SET (fd, &rset);
		maxfd = fd;

		tout.tv_sec = 5;
		tout.tv_usec = 0;

		select (maxfd + 1, &rset, NULL, NULL, &tout);
		if (FD_ISSET (0, &rset)) {	//标准键盘上有输入判断输入集合有没有0(键盘)
			//读取键盘输入,发送到网络套接字fd
			bzero (buf, BUFSIZ);
			do {
				ret = read (0, buf, BUFSIZ - 1);
			} while (ret < 0 && EINTR == errno);
			if (ret < 0) {
				perror ("read");
				continue;
			}
			if (!ret)
				continue;

			if (write (fd, buf, strlen (buf)) < 0) {
				perror ("write() to socket");
				continue;
			}

			if (!strncasecmp (buf, QUIT_STR, strlen (QUIT_STR))) {	//用户输入了quit字符
				printf ("Client is exiting!\n");
				break;
			}
		}

		if (FD_ISSET (fd, &rset)) {	//服务器给发送过来了数据
			//读取套接字数据,处理
			bzero (buf, BUFSIZ);
			do {
				ret = read (fd, buf, BUFSIZ - 1);
			} while (ret < 0 && EINTR == errno);
			if (ret < 0) {
				perror ("read from socket");
				continue;
			}
			if (!ret)
				break;			/* 服务器关闭 */

			//There is a BUG,FIXME!!
			printf ("server said: %s\n", buf);
			if (!strncasecmp (buf, QUIT_STR, strlen (QUIT_STR))) {	//用户输入了quit字符
				printf ("Sender Client is exiting!\n");
				break;
			}

		}
	}

	/*4.关闭套接字 */
	close (fd);
}










select和epoll的区别

linux - Linux IO模式及 select、poll、epoll详解_个人文章 - SegmentFault 思否

(3条消息) 深度理解select、poll和epoll_吓跑毕加索的博客-CSDN博客_select和poll

select有1024的限制和轮询的缺点,由于要从程序态copy到内核态在发送给客户端所以很占用CPU资源。

select是同步的,epoll是异步的,它采用通知机制使得时间复杂度永远为O(1)不随用户增加而增加。用户和内核通过mmap共享一块内存

 通过红黑树将每个文件描述符挂在树上里面是是一个结构体内涵回调函数

创建红黑树返回根节点 ,曾经size表示epoll的大小现在废弃了,系统分配

 

int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);


int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);

 

 


int epoll_pwait(int epfd, struct epoll_event *events,  int maxevents, int timeout, const sigset_t *sigmask);
event:高数内核要监听什么事件

EPOLLIN:表示对应的文件描述符可读

EPOLLOUT:表示对文件描述符可写

EPOLLPRI:表示对应的文件描述符有紧急数据可读

EPOLLERR: 表示对应的文件描述符有错误

EPOLLHUP:表示对应的文件描述符被挂断

EPOLLET:将EPOLL设置为边缘触发,相对于水平促发而言。

 ET模式(边缘触发)(状态发生变化)LT模式(电平触发)

 LT模式和ET模式_干干干就完了的博客-CSDN博客_et模式

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/epoll.h>

#define BUFLEN 128
int createSocket(short port){
	int serverFd,clientFd;
	int len,ret,rlen;
	
	struct sockaddr_in serverAddr;
	len = sizeof(serverAddr);
	serverFd = socket(AF_INET,SOCK_STREAM,0);
	serverAddr.sin_family = AF_INET;
	serverAddr.sin_port = htons(port);
	serverAddr.sin_addr.s_addr = 0; //inet_addr("192.168.3.120");
	int reuse = 1;
	setsockopt(serverFd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(int));

	ret = bind(serverFd,(struct sockaddr *)&serverAddr,len);
	if(ret<0){
		perror("Failed to bind");
		return -1;
	}
	ret = listen(serverFd,10);
	if(ret<0){
		perror("Failed to bind");
		return -1;
	}
	
	return serverFd;
	
	
}

int main(int argc,char ** argv){

	int sockfd;
	short port;
	int addrlen;
	struct sockaddr_in serverAddr,clientAddr;	
	addrlen = sizeof(serverAddr);
	char buf[BUFLEN];
	if(argc!=2){
		printf("Usage:%s port\n",argv[0]);
		return 0;
	}
	port = atoi(argv[1]);
	sockfd = createSocket(port);
    if(sockfd<0){
		return -1;
	}
	int epfd;
	int ret;
	int rdlen;
	int i;
	int clientFd;
	struct epoll_event event;	
	struct epoll_event events[20];
	memset(events,0,20*sizeof(struct epoll_event));
	event.events = EPOLLIN ;
	event.data.fd = sockfd;
	epfd = epoll_create(1);
        
        epoll_ctl(epfd, EPOLL_CTL_ADD, sockfd, &event);

        while(1){

			ret = epoll_wait(epfd, events,20, -1);   //阻塞等待时间到来
            printf("epoll_wait return=%d\n",ret);
                
            for(i=0;i<ret;i++){   //轮训到达的事件
			  if(events[i].data.fd == sockfd){//如果是监听的文件描述符有事件到来,接收新连接
				clientFd = accept(events[i].data.fd,(struct sockaddr *)&clientAddr, &addrlen);
				printf("new client %s,port=%d \n",inet_ntoa(clientAddr.sin_addr),ntohs(clientAddr.sin_port));
				event.events = EPOLLIN;
	            event.data.fd = clientFd;
				epoll_ctl(epfd, EPOLL_CTL_ADD, clientFd, &event);
			}else{   //否则,是连接的客户端事件,读取数据
				rdlen = read(events[i].data.fd,buf,BUFLEN);
				if(rdlen>0){
					printf("read buf=%s\n",buf);
				}else if (rdlen==0){//客户连接中断,删除epoll监听的客户端文件描述符
					event.events = EPOLLIN;
					event.data.fd = events[i].data.fd;
					epoll_ctl(epfd, EPOLL_CTL_DEL, events[i].data.fd, &event);					
				}
			}
		  }
        
        }

}	

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/31822.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

业务流程管理包括什么

​什么是业务流程管理&#xff1f; 业务流程管理 (BPM)提供了一些用于发现、建模、分析、衡量、改进和优化业务策略及流程的方法。 在知名企业中&#xff0c;麦当劳是因为业务流程管理而获得成功的企业之一&#xff0c;标准化业务流程制度是麦当劳成功的关键。 麦当劳为了保证…

CAS号:2578-57-6,H2N-PG-OH

脯氨酸酶的底物(脯氨酸二肽酶)。 编号: 116803中文名称: 二肽Pro-Gly英文名: Pro-GlyCAS号: 2578-57-6单字母: H2N-PG-OH三字母: H2N-Pro-Gly-COOH氨基酸个数: 2分子式: C7H12N2O3平均分子量: 172.18精确分子量: 172.08等电点(PI): 6.11pH7.0时的净电荷数: -0.02平均亲水性: -疏…

MCE | 为什么肥胖经常被“针对”?

近年来&#xff0c;肥胖问题受到越来越多的关注&#xff0c;肥胖不只影响美丽身材&#xff0c;过度肥胖还可能导致肥胖症&#xff0c;这是很多疾病的高风险因素。所以肥胖是一种病&#xff1f;肥胖的标准是什么&#xff1f;别急&#xff0c;等小编慢慢道来。 认识肥胖症 (Obesi…

大数据毕设选题 - 深度学习口罩佩戴检测系统(python OpenCV YOLO)

文章目录0 前言1 课题介绍2 算法原理2.1 算法简介2.2 网络架构3 关键代码4 数据集4.1 安装4.2 打开4.3 选择yolo标注格式4.4 打标签4.5 保存5 训练6 实现效果6.1 pyqt实现简单GUI6.2 图片识别效果6.3 视频识别效果6.4 摄像头实时识别7 最后0 前言 &#x1f525; Hi&#xff0c…

通过ref进行组件间的通信

ref&#xff1a;绑定dom节点&#xff0c;拿到的就是dom对象&#xff1b; ref&#xff1a;绑定组件&#xff0c;拿到的就是组件对象&#xff1b; ref绑在dom节点上&#xff1a; //绑在dom上&#xff0c; <input type"text" ref"mytext"> <input…

SpringCloud微服务(十二)——Seata分布式事务

SpringCloud Alibaba Seata分布式事务 简介 Seata是一款开源的分布式事务解决方案,致力于在微服务架构下提供高性能和简单易用的分布式事务服务 官网&#xff1a;http://seata.io/zh-cn/ 一次业务操作需要垮多个数据源或需要垮多个系统进行远程调用,就会产生分布式事务问题…

PDF的两种密码忘记了,怎么解决

PDF文件带有两种加密方式&#xff0c;大家一定都很熟悉&#xff0c;因为大部分文件都有这两种加密方式&#xff0c;比如Word、Excel、PPT、压缩包等。PDF文件也有这两种密码。 那就是&#xff1a;打开密码、编辑限制 打开密码&#xff1a;就是在我们打开PDF文件的时候&#x…

聚焦离子束FIB测试的计量技术规范盘点

聚焦离子束系统采用聚焦的离子束对样品表面进行轰击&#xff0c;并由计算机控制离子束的扫描或加工轨迹、步距、驻留时间和循环次数&#xff0c;以实现对材料的成像、刻蚀、诱导沉积和注入的分析系统。其应用已经从界面检测扩展到纳米图像制备、透射样品制备、三维成像和分析、…

网络安全加固的必要性

随着信息化的快速变化&#xff0c;企业和机构面临网络安全威胁也越来越多&#xff0c;每一种安全防护措施就像是桶的一块木板&#xff0c;这个木桶中承载着的水就好比网络中运行的各种业务。各种业务能否安全、稳定地运转取决于最矮木板的高度和各块木板之间是否存在缝隙。为了…

加拿大Assignment写作格式技巧整理

对大部分同学来说&#xff0c;写Assignment就如同梦魇一般&#xff0c;让人望而却步。的确&#xff0c;写Assignment是一个大工程&#xff0c;需要为之付诸努力。但是也不必过于担心&#xff0c;小编在本文中主要讨论加拿大英文Assignment的格式及写作技巧&#xff0c;希望能对…

内网使用adb工具使用logcat进行日志分析

WorkTool自动化团队问题发现正文总结问题发现 我们在平时的安卓项目开发中&#xff0c;看日志和调试肯定都是通过 Android Studio 进行实时日志查看和过滤&#xff0c;但如果是部署在内网机器或其他原因不能方便的安装 Android Studio 想查看实时日志就有一定的困难&#xff0…

擎创技术流 | ClickHouse实用工具—ckman教程(4)

《使用CKman导入集群》 CKman&#xff08;ClickHouse Manager&#xff09;是由擎创科技自主研发的一款管理ClickHouse的工具&#xff0c;前端用Vue框架&#xff0c;后端使用Go语言编写。它主要用来管理ClickHouse集群、节点以及数据监控等&#xff0c;致力于服务ClickHouse分布…

双软企业认定需要什么条件

认定双软企业的好处 1、税收优惠:所得税两免三减半。双软认证企业&#xff0c;自获利年度起&#xff0c;第一年和第二年免征企业所得税&#xff0c;第三年至第五年减半征收企业所得税。 增值税超过3%的部分即征即退。 2、政策支持:各地政府对于科研专项资金、税收减免科技计划、…

哈希表【数据结构】

文章目录哈希表概念插入元素搜索元素结构冲突概念冲突-避免哈希函数设计常见哈希函数调节负载因子负载因子定义负载因子和冲突率的关系冲突解决冲突-解决-闭散列线性探测过程缺点二次探测概念缺点冲突-解决-开散列/哈希桶概念结构代码实现哈希桶hashcode 和 equals问题面试题&a…

Metabase学习教程:视图-2

线型图指南 当我们谈论线型图时&#xff0c;我们谈论的多数是&#xff1a;时间序列、趋势线、警报等等。 线型图对于绘制在序列中捕获的数据非常有用&#xff0c;无论该序列是时间的流逝&#xff0c;还是流程或流中的步骤。这些图表通常用于绘制时间序列&#xff08;也称为运…

语义分割实战:基于tensorflow搭建DeeplabV3实现语义分割任务

任务描述: 语义分割是一种典型的计算机视觉问题,其是将一些图像作为输入并将它们转换为具有突出显示的感兴趣区域的掩模,即图像中的每个像素根据其所属的感兴趣对象被分配类别。如下图中左图所示,其语义是人骑自行车,语义分割的结果如右图所示,粉红色代表人,绿色代表自行…

ssm基于安卓android的失物招领APP-计算机毕业设计

技术介绍 开发语言&#xff1a;Java 框架&#xff1a;ssm JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&#xff1a;Maven3.3.9 安卓框架&#x…

Qt MainWindow窗口部件简介

Qt MainWindow窗口部件简介 1、菜单栏 特性如下&#xff1a; 有且仅有一个**位置&#xff1a;**顶部 // 创建菜单 最多只能有一个 QMenuBar * bar menuBar(); // 将菜单栏放入到窗口处 setMenuBar(bar);// 创建顶部菜单 QMenu * fileMenu bar->addMenu("文件&quo…

用DIV+CSS技术制作一个简单的网页 我的家乡主题

家乡旅游景点网页作业制作 网页代码运用了DIV盒子的使用方法&#xff0c;如盒子的嵌套、浮动、margin、border、background等属性的使用&#xff0c;外部大盒子设定居中&#xff0c;内部左中右布局&#xff0c;下方横向浮动排列&#xff0c;大学学习的前端知识点和布局方式都有…

redis三(3-2)

传统缓存的问题 传统的缓存策略一般是请求到达Tomcat后&#xff0c;先查询Redis&#xff0c;如果未命中则查询数据库&#xff0c;存在下面的问题&#xff1a; 请求要经过Tomcat处理&#xff0c;Tomcat的性能成为整个系统的瓶颈Redis缓存失效时&#xff0c;会对数据库产生冲击…