3.0 一般的面试 |
一般的经历 | 得到工作并接受 |
面试过程
腾讯后台面试
面试问题
前些时间去了腾讯面试, 可惜现场没回答好。
是一些基础问题,同时也比较深入的问题。 在此列出来, 欢迎大家讨论交流。
提问(不按时间顺序):
1, 使用Linux epoll模型,水平触发模式(Level-Triggered);当socket可写时,会不停的触发socket可写的事件,如何处理?
2, 从socket读数据时,socket缓存里的数据,可能超过用户缓存的长度,如何处理? 例如,socket缓存有8kB的数据,而你的缓存只有2kB空间。
3, 向socket发送数据时, 可能只发送了用户缓存里的一半,如何处理?例如,需要向socket发送8kB数据,返回值只有2kB发送成功。
4, C 的虚函数是怎么实现的?
5, C 的虚函数有什么作用?
6, 非阻塞connect()如何实现?
7,sizeof()问题
class A
{
char c;
int val;
short sh;
}
class B
{
char c;
int val;
short sh;
void func1(void);
virtual func2(void);
}
sizeof(A), sizeof(B) 分别是多少?
8, 实现字符串比较函数 strcmp(char *src, char * sub)
9, 实现内存拷贝函数 strcpy(void*dst, char * src, size_t len)
10,条件变量的如何使用? 你使用的线程函数是什么?
11, deamon进程如何实现?
12, HTTP和CGI是什么?
13, TCP的三次握手, TIME_WAIT和CLOSE_WAIT状态是什么?
因为第7题之后的属于客观题,不打算在此写答案。 朋友们如有好的答案也欢迎跟贴。
本人在此写出自己对前6个问题的回答:
1, 使用linux epoll模型,水平触发模式(Level-Triggered);当socket可写时,会不停的触发socket可写的事件,如何处理?
第一种最普通的方式:
当需要向socket写数据时,将该socket加入到epoll模型(epoll_ctl);等待可写事件。
接收到socket可写事件后,调用write()或send()发送数据。。。
当数据全部写完后, 将socket描述符移出epoll模型。
这种方式的缺点是: 即使发送很少的数据,也要将socket加入、移出epoll模型。有一定的操作代价。
第二种方式,(是本人的改进方案, 叫做directly-write)
向socket写数据时,不将socket加入到epoll模型;而是直接调用send()发送;
只有当或send()返回错误码EAGAIN(系统缓存满),才将socket加入到epoll模型,等待可写事件后,再发送数据。
全部数据发送完毕,再移出epoll模型。
这种方案的优点: 当用户数据比较少时,不需要epool的事件处理。
在高压力的情况下,性能怎么样呢?
对一次性直接写成功、失败的次数进行统计。如果成功次数远大于失败的次数, 说明性能良好。(如果失败次数远大于成功的次数,则关闭这种直接写的操作,改用第一种方案。同时在日志里记录警告)
在我自己的应用系统中,实验结果数据证明该方案的性能良好。
事实上,网络数据可分为两种到达/发送情况:
一是分散的数据包, 例如每间隔40ms左右,发送/接收3-5个 MTU(或更小,这样就没超过默认的8K系统缓存)。
二是连续的数据包, 例如每间隔1s左右,连续发送/接收 20个 MTU(或更多)。
回来查了资料,发现以下两种方式:
第三种方式: 使用Edge-Triggered(边沿触发),这样socket有可写事件,只会触发一次。
可以在应用层做好标记。以避免频繁的调用 epoll_ctl( EPOLL_CTL_ADD, EPOLL_CTL_MOD)。 这种方式是epoll 的 man 手册里推荐的方式, 性能最高。但如果处理不当容易出错,事件驱动停止。
第四种方式: 在epoll_ctl()使用EPOLLONESHOT标志,当事件触发以后,socket会被禁止再次触发。
需要再次调用epoll_ctl(EPOLL_CTL_MOD),才会接收下一次事件。 这种方式可以禁止socket可写事件,应该也会同时禁止可读事件。会带来不便,同时并没有性能优势,因为epoll_ctl()有一定的操作代价。
2, 从socket读数据时,socket缓存里的数据,可能超过用户缓存的长度,如果处理?
可以调用realloc(),扩大原有的缓存块尺寸。
但是临时申请内存的有一定性能损失。
这种情况要看接收缓存的方式。
第一种方式: 使用100k的大接收缓存为例。
如果要等待数据,并进行解析。可能发生缓存不够的情况。此时只能扩充缓存,或先处理100k的数据,再接收新的数据。
第二种方式: 使用缓存队列,分成8K大小的队列。
不存在接收缓存不够的情况。 除非用户解析已出错,使用数据接收、使用脱勾。 这种方式的代价是,可能需要将缓存队列再次拷贝、拼接成一块大的缓存,再进行解析。 而在本人的系统中,只需要将socket接收的数据再次原样分发给客户, 所以这种方案是最佳方案。
3, 向socket发送数据时, 可能只发送了用户缓存里的一半,然后失败,如何处理?
记录缓存的偏移量。 下一次socket写事件时, 再从偏移的位置接着发送。
那个面试官居然对这个问题问了我两次, 看来我解释的不够清晰。。。。。。 郁闷。
4, C 的虚函数是怎么实现的?
使用虚函数表。
回来查下资料: C 对象使用虚表, 如果是基类的实例,对应位置存放的是基类的函数指针;如果是继承类,对应位置存放的是继承类的函数指针(如果在继承类有实现)。所以,当使用基类指针调用对象方法时,也会根据具体的实例,调用到继承类的方法。
5, C 的虚函数有什么作用?
虚函数作用是实现多态, 很多人都能理解这一点。但却不会回答下面这一点。
更重要
是一些基础问题,同时也比较深入的问题。 在此列出来, 欢迎大家讨论交流。
提问(不按时间顺序):
1, 使用Linux epoll模型,水平触发模式(Level-Triggered);当socket可写时,会不停的触发socket可写的事件,如何处理?
2, 从socket读数据时,socket缓存里的数据,可能超过用户缓存的长度,如何处理? 例如,socket缓存有8kB的数据,而你的缓存只有2kB空间。
3, 向socket发送数据时, 可能只发送了用户缓存里的一半,如何处理?例如,需要向socket发送8kB数据,返回值只有2kB发送成功。
4, C 的虚函数是怎么实现的?
5, C 的虚函数有什么作用?
6, 非阻塞connect()如何实现?
7,sizeof()问题
class A
{
char c;
int val;
short sh;
}
class B
{
char c;
int val;
short sh;
void func1(void);
virtual func2(void);
}
sizeof(A), sizeof(B) 分别是多少?
8, 实现字符串比较函数 strcmp(char *src, char * sub)
9, 实现内存拷贝函数 strcpy(void*dst, char * src, size_t len)
10,条件变量的如何使用? 你使用的线程函数是什么?
11, deamon进程如何实现?
12, HTTP和CGI是什么?
13, TCP的三次握手, TIME_WAIT和CLOSE_WAIT状态是什么?
因为第7题之后的属于客观题,不打算在此写答案。 朋友们如有好的答案也欢迎跟贴。
本人在此写出自己对前6个问题的回答:
1, 使用linux epoll模型,水平触发模式(Level-Triggered);当socket可写时,会不停的触发socket可写的事件,如何处理?
第一种最普通的方式:
当需要向socket写数据时,将该socket加入到epoll模型(epoll_ctl);等待可写事件。
接收到socket可写事件后,调用write()或send()发送数据。。。
当数据全部写完后, 将socket描述符移出epoll模型。
这种方式的缺点是: 即使发送很少的数据,也要将socket加入、移出epoll模型。有一定的操作代价。
第二种方式,(是本人的改进方案, 叫做directly-write)
向socket写数据时,不将socket加入到epoll模型;而是直接调用send()发送;
只有当或send()返回错误码EAGAIN(系统缓存满),才将socket加入到epoll模型,等待可写事件后,再发送数据。
全部数据发送完毕,再移出epoll模型。
这种方案的优点: 当用户数据比较少时,不需要epool的事件处理。
在高压力的情况下,性能怎么样呢?
对一次性直接写成功、失败的次数进行统计。如果成功次数远大于失败的次数, 说明性能良好。(如果失败次数远大于成功的次数,则关闭这种直接写的操作,改用第一种方案。同时在日志里记录警告)
在我自己的应用系统中,实验结果数据证明该方案的性能良好。
事实上,网络数据可分为两种到达/发送情况:
一是分散的数据包, 例如每间隔40ms左右,发送/接收3-5个 MTU(或更小,这样就没超过默认的8K系统缓存)。
二是连续的数据包, 例如每间隔1s左右,连续发送/接收 20个 MTU(或更多)。
回来查了资料,发现以下两种方式:
第三种方式: 使用Edge-Triggered(边沿触发),这样socket有可写事件,只会触发一次。
可以在应用层做好标记。以避免频繁的调用 epoll_ctl( EPOLL_CTL_ADD, EPOLL_CTL_MOD)。 这种方式是epoll 的 man 手册里推荐的方式, 性能最高。但如果处理不当容易出错,事件驱动停止。
第四种方式: 在epoll_ctl()使用EPOLLONESHOT标志,当事件触发以后,socket会被禁止再次触发。
需要再次调用epoll_ctl(EPOLL_CTL_MOD),才会接收下一次事件。 这种方式可以禁止socket可写事件,应该也会同时禁止可读事件。会带来不便,同时并没有性能优势,因为epoll_ctl()有一定的操作代价。
2, 从socket读数据时,socket缓存里的数据,可能超过用户缓存的长度,如果处理?
可以调用realloc(),扩大原有的缓存块尺寸。
但是临时申请内存的有一定性能损失。
这种情况要看接收缓存的方式。
第一种方式: 使用100k的大接收缓存为例。
如果要等待数据,并进行解析。可能发生缓存不够的情况。此时只能扩充缓存,或先处理100k的数据,再接收新的数据。
第二种方式: 使用缓存队列,分成8K大小的队列。
不存在接收缓存不够的情况。 除非用户解析已出错,使用数据接收、使用脱勾。 这种方式的代价是,可能需要将缓存队列再次拷贝、拼接成一块大的缓存,再进行解析。 而在本人的系统中,只需要将socket接收的数据再次原样分发给客户, 所以这种方案是最佳方案。
3, 向socket发送数据时, 可能只发送了用户缓存里的一半,然后失败,如何处理?
记录缓存的偏移量。 下一次socket写事件时, 再从偏移的位置接着发送。
那个面试官居然对这个问题问了我两次, 看来我解释的不够清晰。。。。。。 郁闷。
4, C 的虚函数是怎么实现的?
使用虚函数表。
回来查下资料: C 对象使用虚表, 如果是基类的实例,对应位置存放的是基类的函数指针;如果是继承类,对应位置存放的是继承类的函数指针(如果在继承类有实现)。所以,当使用基类指针调用对象方法时,也会根据具体的实例,调用到继承类的方法。
5, C 的虚函数有什么作用?
虚函数作用是实现多态, 很多人都能理解这一点。但却不会回答下面这一点。
更重要
面试其它细节
获取职位的方式:网络上面
面试时间:2008-2
在面试过程参加了:1对1面试 IQ测试
湖北成教网 武汉纺织大学成教
武汉轻工大学成教
湖北师范大学成教
武汉工程大学成教
长江大学成教
湖北科技学院成教
荆州教育学院成教
荆楚理工学院成教
湖北开放职业学院成教
湖北中医药高等专科学校成教
湖北理工学院成教
荆州理工职业学院成教
湖北国土资源职业学院成教
中南财经政法大学成教
武汉大学成教
武汉理工大学成教
武汉科技大学成教
华中农业大学成教
湖北工业大学成教
湖北中医药大学成教
武汉成人高考网
孝感成人高考网
荆州成人高考网
咸宁成人高考网
宜昌成人高考网
襄阳成人高考网
十堰成人高考网
武汉自考网
黄冈自考网
宜昌自考网
襄阳自考网
十堰自考网
湖北成人高考报名网
湖北自考报名网
湖北大学成教
湖北工业大学成教
湖北中医药大学成教
华中农业大学成教
武汉大学成教网
武汉科技大学成教
武汉理工大学成教
中南财经政法大学成教
上海成考网
上海自考网
中南财经政法大学自考
中南财经政法大学自考
华中师范大学自考招生网
武汉理工大学自考
湖北大学自考
华中农业大学自考
湖北中医药大学自考
湖北工业大学自考
华中师范大学自考招生网
湖北中医药大学成教
湖北中医药大学成教
武汉理工大学成教
武汉科技大学成教
武汉大学成教
湖北工业大学成教
湖北大学成教
华中农业大学成教
中南财经政法大学成教
华中师范大学成教
湖北中医药大学自考
武汉理工大学自考
武汉大学自考
湖北工业大学自考
湖北大学自考
华中农业大学自考
中南财经政法大学自考
华中师范大学自考