嵌入式面试题
创始人
2024-02-11 19:48:16
0

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

#include 
#include 
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");elseprintf("转换成功, 现在是⽹络字节序了\n");}return 0;
}

2、说下select和epoll的区别;

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

用select实现服务器端

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include typedef struct sockaddr Addr;
typedef struct sockaddr_in Addr_in;
typedef struct Node{int fd;struct Node *next;
}Node;#define BACKLOG 5void 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 1p = H;puts("");printf("Node:");while(p != NULL){printf("%d ", p->fd);p = p->next;}
#endifif(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 0sin.sin_addr.s_addr = inet_addr (SERV_IP_ADDR);
#elseif (inet_pton (AF_INET, argv[1], (void *) &sin.sin_addr) != 1) {perror ("inet_pton");exit (1);}
#endifif (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(键盘)//读取键盘输入,发送到网络套接字fdbzero (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 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include #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;i0){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);					}}}}}	

 

相关内容

热门资讯

喜欢穿一身黑的男生性格(喜欢穿... 今天百科达人给各位分享喜欢穿一身黑的男生性格的知识,其中也会对喜欢穿一身黑衣服的男人人好相处吗进行解...
发春是什么意思(思春和发春是什... 本篇文章极速百科给大家谈谈发春是什么意思,以及思春和发春是什么意思对应的知识点,希望对各位有所帮助,...
网络用语zl是什么意思(zl是... 今天给各位分享网络用语zl是什么意思的知识,其中也会对zl是啥意思是什么网络用语进行解释,如果能碰巧...
为什么酷狗音乐自己唱的歌不能下... 本篇文章极速百科小编给大家谈谈为什么酷狗音乐自己唱的歌不能下载到本地?,以及为什么酷狗下载的歌曲不是...
华为下载未安装的文件去哪找(华... 今天百科达人给各位分享华为下载未安装的文件去哪找的知识,其中也会对华为下载未安装的文件去哪找到进行解...
家里可以做假山养金鱼吗(假山能... 今天百科达人给各位分享家里可以做假山养金鱼吗的知识,其中也会对假山能放鱼缸里吗进行解释,如果能碰巧解...
四分五裂是什么生肖什么动物(四... 本篇文章极速百科小编给大家谈谈四分五裂是什么生肖什么动物,以及四分五裂打一生肖是什么对应的知识点,希...
怎么往应用助手里添加应用(应用... 今天百科达人给各位分享怎么往应用助手里添加应用的知识,其中也会对应用助手怎么添加微信进行解释,如果能...
客厅放八骏马摆件可以吗(家里摆... 今天给各位分享客厅放八骏马摆件可以吗的知识,其中也会对家里摆八骏马摆件好吗进行解释,如果能碰巧解决你...
美团联名卡审核成功待激活(美团... 今天百科达人给各位分享美团联名卡审核成功待激活的知识,其中也会对美团联名卡审核未通过进行解释,如果能...