某公司面试总结

      去某有点名气的互联网公司面试云存储服务器工程师(unix平台),了解到自己的不足,当然可能应聘的岗位与自己的几年工作经历方向上不大一致,不过也看出来自己对某些深一点的系统知识并不能准确理解,现把问到的部分问题总结一下,并加上自己后来网上搜索博客看到的大致答案。

1. 多进程读写文件是否需要加锁?

    这里涉及到文件在内存中是怎样的存在,参考https://blog.csdn.net/zhangyifei216/article/details/76653746。每次调用open(fopen内部也是调用的open)时,返回的文件句柄都关联了一个独立struct file对象(内有一个文件读写偏移量),也就是说多次打开同一个硬盘上的文件时,会产生多个struct file对象,而这些file对象又会都关联到系统内存里同一个inode文件对象,inode对象维持了一个被open的计数,当计数为0时,inode才会从内存中移出。

        每个inode对象都带了一个互斥锁,而每次系统调用read和write内部都用到了inode对象的互斥锁锁进行加解锁,也即是说read和write都是原子操作。write有个要求写入数据大小参数,返回了一个实际写入数据大小值,在写文件时返回值要么是0,要么通常就是要求写入的数据大小值,尚不确定数据量比较大时是否会出现大于0又小于要求写入的大小值,假定要么全不写要么全部写入了。

       既然读写操作是原子操作,那么多进程(每个进程有一个struct file对象,那么就有多个struct file对象,后不再说明) 读写同一inode文件在安全上来说是不需要加锁的,但是从数据一致性上来说多进程写文件时,可能发生数据覆盖,因为可能两个进程都是在同一偏移量处写入,前一次被后一次写入覆盖。

       注:fork产生的父子进程会共享一个struct file对象,其读写会相互影响偏移量,但还是不需要加锁。

       多线程读写同一文件呢?多线程各自打开了一个struct file,与多进程类似,因为read和write的原子性,也不需要加锁;多线程共享一个struct file,与fork产生的父子进程类似,还是不需要加锁。

2.多线程写操作是否会产生混乱数据,如线程A写“AAAAAA”,线程B写"BBBBBB",是否会出现"AAABBBAAABBB"?

         不会,因为读写操作的原子性,一次全部写完,只会出现"AAAAAABBBBBB"、"BBBBBBAAAAAA"、

"AAAAAA"、"BBBBBB"4种情况,即追加或者覆盖的情况,而不会混叉。

3.多进程写日志如何保证数据一致性(不发生数据覆盖)?

       我想的答案是日志数据以队列的方式让单线程去写文件,有些系统设计的单独的一个写日志进程也是一个意思,总之就是把多进程的日志数据抛给某个独立的日志线程去写文件。当然这个相对而言是复杂了点,技术面试官也问能不能有个更简单点的方法,我也没想到,后来查了一下,没错,各进程以追加方式打开日志文件写就行了,在追加模式下,每次写的时候会先把文件偏移到末尾,再写,而且这是个原子操作。

4.mmap内存映射与read/write读写文件的区别?

        物理内存与进程虚拟内存空间是通过内存映射(分页内存管理、分段内存管理、段页式内存管理),进程虚拟内存空间又分为内核空间和用户空间,文件加载到物理内存的内核空间。

        read文件是先将文件加载到内核空间,再把数据从内核空间拷贝到用户空间,write文件的过程是需要用户空间的数据拷贝到内核空间,再写回到磁盘。

       内存映射是将硬盘文件的指定区间数据映射加载到物理内存内核空间,再直接映射到用户进程的虚拟地址用户空间,进程可对映射的用户空间内存进行直接访问修改,调用msync立即同步更新到文件或者调用munmap时会自动更新到文件。相对于read/write而言,少了一次内核空间与用户空间之间的拷贝过程,效率更高,而且多进程可共享该映射内存区域,实现数据共享及进程通信。

5.tcp和udp是否可以共用一个端口,为什么?

       可以。因为协议不同,传输层包头中有指明协议是tcp还是udp,套接字就是靠客户端和服务器的ip端口以及协议构成的五元组标识的。所以同一层的不同协议(tcp和udp都属于控制层协议)可以使用相同的端口。

6.epoll IO多路复用模型?ET(edge triggered,边缘触发)和LT(level triggered,水平触发)的区别?

        epoll模型:略。优势就是,相对于select/poll而言,监控socket数量上没有限制,采用内核事件回调的方式而不需要在内核态与用户态之间来回拷贝socket句柄数组,且监控只返回有事件的socket,所以效率更高。

        边缘触发:只在读写缓冲区状态有变化时才会触发事件,也就意味着如果触发了一次可读事件后而数据没有被读完,则再次监控时得不到读剩余数据的读事件。

       水平触发:只要缓冲区有数据可读,就会触发事件。

7.sql注入?如何防止?

       略

8.mysql 分表?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值