0%

Buffer和Cache的区别

buffer与cache操作的对象就不一样。

buffer(缓冲)是为了提高内存和硬盘(或其他I/0设备)之间的数据交换的速度而设计的。

cache(缓存)是为了提高cpu和内存之间的数据交换速度而设计,也就是平常见到的一级缓存、二级缓存、三级缓存。

cpu在执行程序所用的指令和读数据都是针对内存的,也就是从内存中取得的。由于内存读写速度慢,为了提高cpu和内存之间数据交换的速度,在cpu和内存之间增加了cache,它的速度比内存快,但是造价高,又由于在cpu内不能集成太多集成电路,所以一般cache比较小,以后intel等公司为了进一步提高速度,又增加了二级cache,甚至三级cache,它是根据程序的局部性原理而设计的,就是cpu执行的指令和访问的数据往往在集中的某一块,所以把这块内容放入cache后,cpu就不用在访问内存了,这就提高了访问速度。当然若cache中没有cpu所需要的内容,还是要访问内存的。

缓冲(buffers)是根据磁盘的读写设计的,把分散的写操作集中进行,减少磁盘碎片和硬盘的反复寻道,从而提高系统性能。linux有一个守护进程定期清空缓冲内容(即写入磁盘),也可以通过sync命令手动清空缓冲。举个例子吧:我这里有一个ext2的U盘,我往里面cp一个3M的MP3,但U盘的灯没有跳动,过了一会儿(或者手动输入sync)U盘的灯就跳动起来了。卸载设备时会清空缓冲,所以有些时候卸载一个设备时要等上几秒钟。

修改/etc/sysctl.conf中的vm.swappiness右边的数字可以在下次开机时调节swap使用策略。该数字范围是0~100,数字越大越倾向于使用swap。默认为60,可以改一下试试。–两者都是RAM中的数据。

简单来说,buffer是即将要被写入磁盘的,而cache是被从磁盘中读出来的。

buffer是由各种进程分配的,被用在如输入队列等方面。一个简单的例子如某个进程要求有多个字段读入,在所有字段被读入完整之前,进程把先前读入的字段放在buffer中保存。

cache经常被用在磁盘的I/O请求上,如果有多个进程都要访问某个文件,于是该文件便被做成cache以方便下次被访问,这样可提高系统性能。

cgi和fastcgi的区别

最早的Web服务器只处理静态的html文件

随着技术的不断发展,网站越来越复杂,然后出现到动态网站,但是服务并不能直接运行php,asp这个的动态语言文件
然后出现了cgi,cgi只是接口协议

cgi是怎么执行动态请求的

web服务器接受到请求,然后根据内容,fork一个新进程,这个进程会把处理完的数据返回给web服务器,最后web服务器把内容发送给用户,刚才fork的进程也随之退出,如果下次用户还请求改动态脚本,那么web服务器又再次fork一个新进程。这个方式的问题在与每次请求都要新开一个进程,用完之后又要关闭,这是CGI最为人诟病的fork-and-execute 模式,效率上比较低。

后来出现了一种更高级的方式,web服务器收到一个请求时,他不会重新fork一个进程(因为这个进程在web服务器启动时就开启了,而且不会退出),web服务器直接把内容传递给这个进程,这个进程收到请求后进行处理,把结果返回给web服务器,最后自己接着等待下一个请求的到来,而不是退出。 这就是fastcgi。

什么是死锁,如何避免死锁?

线程A需要资源X,而线程B需要资源Y,而双方都掌握有对方所要的资源,这种情况称为死锁(deadlock),或死亡拥抱(the deadly embrace)。

在并发程序设计中,死锁 (deadlock) 是一种十分常见的逻辑错误。通过采用正确的编程方式,死锁的发生不难避免。

死锁的四个必要条件

在计算机专业的本科教材中,通常都会介绍死锁的四个必要条件。这四个条件缺一不可,或者说只要破坏了其中任何一个条件,死锁就不可能发生。我们来复习一下,这四个条件是:

  1. 互斥(Mutual exclusion):存在这样一种资源,它在某个时刻只能被分配给一个执行绪(也称为线程)使用;

  2. 持有(Hold and wait):当请求的资源已被占用从而导致执行绪阻塞时,资源占用者不但无需释放该资源,而且还可以继续请求更多资源;

  3. 不可剥夺(No preemption):执行绪获得到的互斥资源不可被强行剥夺,换句话说,只有资源占用者自己才能释放资源;

  4. 环形等待(Circular wait):若干执行绪以不同的次序获取互斥资源,从而形成环形等待的局面,想象在由多个执行绪组成的环形链中,每个执行绪都在等待下一个执行绪释放它持有的资源。

解除死锁的必要条件

不难看出,在死锁的四个必要条件中,第二、三和四项条件比较容易消除。通过引入事务机制,往往可以消除第二、三两项条件,方法是将所有上锁操作均作为事务对待,一旦开始上锁,即确保全部操作均可回退,同时通过锁管理器检测死锁,并剥夺资源(回退事务)。这种做法有时会造成较大开销,而且也需要对上锁模式进行较多改动。

消除第四项条件是比较容易且代价较低的办法。具体来说这种方法约定:上锁的顺序必须一致。具体来说,我们人为地给锁指定一种类似“水位”的方向性属性。无论已持有任何锁,该执行绪所有的上锁操作,必须按照一致的先后顺序从低到高(或从高到低)进行,且在一个系统中,只允许使用一种先后次序。

请注意,放锁的顺序并不会导致死锁。也就是说,尽管按照 锁A, 锁B, 放A, 放B 这样的顺序来进行锁操作看上去有些怪异,但是只要大家都按先A后B的顺序上锁,便不会导致死锁。
解决方法:

1 使用事务时,尽量缩短事务的逻辑处理过程,及早提交或回滚事务; (细化处理逻辑,执行一段逻辑后便回滚或者提交,然后再执行其它逻辑,直到事物执行完毕提交)

2 设置死锁超时参数为合理范围,如:3分钟-10分种;超过时间,自动放弃本次操作,避免进程悬挂;

3 优化程序,检查并避免死锁现象出现;

4 .对所有的脚本和SP都要仔细测试,在正是版本之前。

5 所有的SP都要有错误处理(通过@error)

6 一般不要修改SQL SERVER事务的默认级别。不推荐强行加锁

另外参考的解决方法:

按同一顺序访问对象
如果所有并发事务按同一顺序访问对象,则发生死锁的可能性会降低。例如,如果两个并发事务获得 Supplier 表上的锁,然后获得 Part 表上的锁,则在其中一个事务完成之前,另一个事务被阻塞在 Supplier 表上。第一个事务提交或回滚后,第二个事务继续进行。不发生死锁。将存储过程用于所有的数据修改可以标准化访问对象的顺序。

避免事务中的用户交互
避免编写包含用户交互的事务,因为运行没有用户交互的批处理的速度要远远快于用户手动响应查询的速度,例如答复应用程序请求参数的提示。例如,如果事务正在等待用户输入,而用户去吃午餐了或者甚至回家过周末了,则用户将此事务挂起使之不能完成。这样将降低系统的吞吐量,因为事务持有的任何锁只有在事务提交或回滚时才会释放。即使不出现死锁的情况,访问同一资源的其它事务也会被阻塞,等待该事务完成。

保持事务简短并在一个批处理中
在同一数据库中并发执行多个需要长时间运行的事务时通常发生死锁。事务运行时间越长,其持有排它锁或更新锁的时间也就越长,从而堵塞了其它活动并可能导致死锁。保持事务在一个批处理中,可以最小化事务的网络通信往返量,减少完成事务可能的延迟并释放锁。

使用低隔离级别
确定事务是否能在更低的隔离级别上运行。执行提交读允许事务读取另一个事务已读取(未修改)的数据,而不必等待第一个事务完成。使用较低的隔离级别(例如提交读)而不使用较高的隔离级别(例如可串行读)可以缩短持有共享锁的时间,从而降低了锁定争夺。

使用绑定连接
使用绑定连接使同一应用程序所打开的两个或多个连接可以相互合作。次级连接所获得的任何锁可以象由主连接获得的锁那样持有,反之亦然,因此不会相互阻塞。

守护进程也称精灵进程(Daemon),是运行在后台的⼀一种特殊进程。它独立于控制终端且周期性地执行某种任务或等待处理某些发生的事件。守护进程是⼀一种很有用的进程。Linux的大多数服务器就是用守护进程实现的。比如,Internet服务器inetd,Web服务器httpd等。同时,守护进程完成许多系统任务。比如,作业规划进程crond等。Linux系统启动时会启动很多系统服务进程,用ps axj命令查看系统中的进程(参数a表示不仅列当前用户的进程,也列出所有其他用户的进程,参数x表示不仅列有控制终端的进程,也列出所有无控制终端的进程,参数j表示列出与 作业控制相关的信息)。

凡是TPGID一栏写着-1的都是没有控制终端的进程,也就是守护进程。在COMMAND一列用[] 括起来的 名字表示内核线程,这些线程在内核里创建,没有用户空间代码,因此没有程序文件名和命令行, 通常采用以k开头的名字,表示Kernel。init进程我们已经很熟悉了,udevd负责维护/dev目录下的 设备文件,acpid负责电源管理,syslogd负责维护/var/log下的日志文件,可以看出,守护进程通 常采用以d结尾的名字,表示Daemon。

unlink 用于删除文件名。删除文件名是指在原目录下不再含有此文件名。要注意的是,这里的表述是删除文件名,并不一定删除磁盘上文件的内容。只有在文件的链接数为1,即当前文件名是文件的最后一个链接并且有没有进程打开此文件的时候,unlink() 才会真正删除文件内容。用 unlink 真正的删除一个文件内容,必须同时满足以上两个条件。

如果文件链接数为1,但是仍然有进程打开这一文件,那么 unlink 后,虽然在原目录中已经没有了被删除文件的名字,但是实际上系统还是保留了这一文件,直到打开这一文件的所有进程全部关闭此文件后,系统才会真正删除磁盘上的文件内容。由此可见,用unlink直接删除打开的文件是安全的。删除已经打开的文件,对使用此文件的进程,不会有任何影响,也不会导致进程崩溃(注意这里讨论的是删除已被打开的文件,通常是数据文件,并未讨论删除正在运行的可执行文件)。
rm 命令比 unlink 命令多了一些权限的检查,之后也是调用了 unlink() 系统调用。在文件允许删除的情况下,rm 命令和 unlink 命令其实是没有区别的。

mv 的主要功能就是检查初始文件和目标文件是否存在及是否有访问权限,之后执行 rename 系统调用,因而,当目标文件存在时,mv 的行为由 rename() 系统调用决定,即类似于删除文件后再重建一个同名文件。

在执行cp 命令之后,文件的 inode 号并没有改变,并且可以看出,cp 使用了 open 及O_TRUNC 参数打开了目标文件。因而当目标文件已经存在时,cp 命令实际是清空了目标文件内容,之后把新的内容写入目标文件。