1.时钟:tsc可得到更精确时间,通过读取其寄存器;nohz是将最近的timer设置为下一个中断的
ptrace:单步
字符集与编码:
磁盘io调度:EIOCBRETRY返回和EIOCBQUEUED,前者无法完成,后者未知
2.big endian /little endian:强制类型转换时,后者占优势,有符号运算时,前者占优势
缓冲区溢出:栈溢出,堆溢出
ssl 与ipsec 的对比
main函数之前,包括linux和windows以及winmain和main的关系
3.证书申请的签名密钥对和证书中的公钥和加解密私钥
msi中断
napi/dma
acpi/apm
4.内核系统调用的参数传递,在sys_execve中只有一个pt_regs参数,是值传递,因此你不能破坏栈的平衡
linux信号返回sigreturn
linux2.6的input子系统:输入子系统核心层( Input Core ),驱动层和事件处理层(Event Handler)三部份组成。 input子系统通过分层将一个输入设备的输入过程分隔为独立的两部份:驱动到Input Core,Input Core到Event Handler。所 以整个链路的这两部分的接口的创建是独立的传值和传引用只是语言级别的语义,而实现完全是另一回事,可以用指针实现,重点看汇编代码,落实到lea和 mov的区别,实际上理解堆栈就可以了。
时序电路实现硬连线,比微指令快
5.intel的vt-d技术提供了虚拟化(处理器虚拟化,io虚拟化)。 linux的kvm实现了vt-d的软件层
6.自己可以实现setjmp和longjmp,就是在setjmp中保存堆栈,在longjmp中恢复(实际上就是覆盖),通过这个思考,可以想 象可以通过c语言得到堆栈指针。sigreturn相关的知识。pam认证
7.最新调度,实时组调度
FIFO RR调度策略
cpu运行队列负载均衡策略
cgroups
slub分配器
verify_area交给硬件来完成,通过异常表
8.时钟中断中的eventdevice和clocksouce的双链表,2.6内核中有很多双链表结构,在内核中有很多地方重新更新运行队列的时钟
9. 在中断返回到内核空间时抢占之前要测试当前进程在进入中断之前,中断是否是开着的。有人可能问了,关了中断,他就不能走到这步了。其实不然,我们不要忘记了那些不可屏蔽的中断,或称他们为异常,他们即使是在关闭中断的条件下,仍然可能跑到这里。但是为什么开着中断的情况下引起的异常是能够引起调度的?因 为,这表明那个程式没有处于原子上下文,所以,还是能够安全地被调度的。
10.{在hw_interrupt_type的ack中可能调用spin_lock_irqsave来禁用中断,但是当__do_IRQ执行到handle_IRQ_event时会检查注册的中断类型,如果是 SA_INTERRUPT则重新开启中断}前面说的大错特错,中断禁用是在进入中断门的时候禁用的
11.call_usermodehelper() 执行之后会在工作队列khelper_wq 中加入一个工作线程__call_usermodehelper,这个工作队列上的线程运行之后,会根据wait的类型,调用kernel_thread 启用相应类型的线程wait_for_helper()或____call_usermodehelper(),之所以调用kernel_thread 生成新的线程,目的在于让并行运行实现最大化,充分利用cpu.
12.Linux遭遇扩展性问题:每cpu的内核线程使得系统内的线程队 列加长,如果在很多cpu的机器上,(针对那些为每个处理器都建立一个内核线程)这个链表更长,不如在延迟不大的情况下直接用khelper工作队列来代 理,或者将内核线程不作为init的子线程,或者为僵尸进程(zombie process)建立不同的链表,或者减少内核线程的数量,内核线程和用户的关系不大
13.2.6.20版本之后使用工作队列需要把work_struct定义在用户的数据结构中,然后通过container_of来得到用户数据。
14.vista的SuperFetch不错,它用到了内存优先级和io优先级,这些都是vista的杰作
15.内碎片,外碎片与段式管理还有页式管理
16.完全公平调度中有两种方案可用,一是传统的间隔时钟中断,二是hrtimer回调,这些设计的都很不错,值得一读。引入sched_class以后,调度更
加模块化了,原来的就明显臃肿了,原因有二,一是调度算法,采用优先级时间片调度,显然要考虑很多,比如动态优先级;二是代码结构。
17.如果采用了传统时钟间隔中断法,那么每个tick函数后都要判断是否要调度,如果采用hrtimer法,则要每次执行“运行队列”的hrtimer回调函数
后 都要重新调度,不是因为别的,而是要重新把进程在红黑树里面排序,判断next进程,而这一切全在调度函数里面,这么做纯粹是个代码结构问题,我对于 hrtick_start_fair这个函数百思不得其解,后来知道这是为下一次统计安装了一个timer的前提,首先计算进程p还能运行多久,然后在那 个时间段过后timer到期,这个只有在next进程和当今进程不等的情况下设定
18.粗略看了一下x window的实现,以及x驱动,注意/lib/module/XXX/kernel/driver/vidio/下的是内核模块,而/usr/X11R6/lib/module/driver/下
的是xwindow驱动,它是运行在用户空间的,通过调用内核导出的接口来工作,而是否应用硬件加速以及有没有硬件加速就看他们配合了
19.lock前缀可以锁总线,但是最新的实现可以锁缓存,这样效率更高,当然由硬件实现mesi协议以保持缓存一致性
20.tcp的syn cookie可以防止dos攻击,具体由两种方式,一是内核实现的cookie计算,另一种防dos的方式是利用监控程序监控tcp半连接,驱动地址
状态机转换。很值得称道的是isn的组织,位运算的巧妙
21.日志文件系统的事务性质,研究ext3和reiserfs还有xfs,再考虑它们组织数据的方式,比如b+树或链表。b+树
22.linux内存回收的时候要用lru算法,具体linux的内核的实现是用了两个链表,然后在这两个链表上来回根据策略移动页面,把最终被移动到inactive的页面回收掉。
23.lru算法可由硬件矩阵实现,非常巧妙
24.内核怕在不允许睡眠的路径上内存分配失败,所以每个10秒唤醒kswapd,他和pdflush不同
25.每当一个进程被唤醒的时候都要检测是否需要重新调度,这在新版本内核中被纳入了sched_class的管理范畴。check_preempt_wakeup是cfs中的判断,不能抢占别的进程组的进程,因为那样对别的组不公平,这就是基于组的策略
26. 内核线程相关的东西今天又好好学习了一下,在内核空间调用系统调用都知道要用set_fs把界限限制在4g,但是要知道在系统初启时,current就是 一个内核线程,他的界限被限制到4g,因此它就可以安全并成功地调用系统调用exec,从而开始用户空间之旅,开始了生命周期。在 load_elf_binary中调用start_thread设置新的界限,就是set_fs(USER_DS)。
27.int default_wake_function(wait_queue_t *curr, unsigned mode, int sync, void *key)
{
return try_to_wake_up(curr->private, mode | TASK_RUNNING_MUTEX,
sync, 0);
}
28.cpu TLB的懒惰模式(处理器间中断)
task_t * context_switch(runqueue_t *rq, task_t *prev, task_t *next)
{
struct mm_struct *mm = next->mm;
struct mm_struct *oldmm = prev->active_mm;
if (unlikely(!mm)) {
next->active_mm = oldmm;
atomic_inc(&oldmm->mm_count);
enter_lazy_tlb(oldmm, next);
} else
switch_mm(oldmm, mm, next);
if (unlikely(!prev->mm)) {
prev->active_mm = NULL;
WARN_ON(rq->prev_mm);
rq->prev_mm = oldmm;
}
switch_to(prev, next, prev);
return prev;
}
29.iret的意义
30.内核线程可以使用use_mm来挂接用户空间,内核线程一般通过daemonize来解除父线程mm_struct的引用,这个是通过内核线程自己来做的,内核管理代码并没有强制,实际上父线程退出以后mm的引用计数就会递减,直到0后删除
31.fork的子进程如果不和父进程共享mm,则为了不cow,那么要先运行,通过加到运行队列首部实现
32.schedule_tail 必须在fork之后抽时间调用,因为他要finish_task_switch,完成一些善后处理,大家都知道,这个函数一般在schedule中调用,也就是刚刚完成调度的时候,换句话说就是一个进程刚刚被唤醒的时候,那么一个刚刚fork出的进程并没有从schedule被唤醒,所以它就要在fork 完成以后手动调用finish_task_switch了。实际上,在schedule中的switch_to里,就是通过保存和恢复 t->thread.eip来完成的,所以在fork里,也就是通过设置新进程的thread->eip等于ret_from_form来强 制执行善后工作的
33.switch_to这个宏还是要深刻理解的,为什么pushl %6/n/t就能保证新进程从标号1开始呢,这是因为接下来的jmp __switch_to中__switch_to的最后又一个return,这样就要弹出eip了
34.TSS与任务切换:linux不用任务门进行切换
35.sysenter指令同样从linux不使用任务门中得到了好处
36.缺页中断处理中一定将进程设置为running,否则一旦睡眠将没有人将他唤醒--僵尸?不!它的一切资源还在
37.daemonize("khubd");allow_signal(SIGKILL);前后这么设置,前者屏蔽一切信号,后者打开SIGKILL信号,这一般在内核线程里面用到,所以内核线程也不一定是杀不掉的,就看你怎么设置。
38.不能通过编程屏蔽SIGKILL不是什么神奇的事情,就是在系统调用中作了一下拦截
39.至于说本进程退出,父进程收尸,那只是posix的约定
40.返回用户空间前要调用do_notify_resume,在这里调用hrtick_resched来重新安装hrtimer
41.aio 实现的异步io实际上目前必须以O_DIRECT的方式打开文件,这样它就可以直接在应用程序和磁盘之间传输数据,注意aio_ring映射的是io结 果,而不是实际数据,实际数据在retry读写中就已经传输过了tcp滑动窗口,网络的流量整形,linux的相应实现,实现了树形的策略接口,可以实现 基于类的规则和无类规则,数据报的调度非常美妙。一个排队实体由排队规则,过滤器和类组成,就是它们组成了树形结构,linux同样实现了 FIFO,PQ,CQ, WFQ,CBWFQ等拥塞管理机制,并且必须配置,而且实现了基于令牌桶的流量整形机制
42.ppu物理加速--为了分离出物理运算;intel-hd audio与ac97的对比;支持dx10的显卡(统一着色)
43.bios自检过程
44.重新审视了为什么系统复位的时候从最高地址下开始执行,原来是因为a20地址总线网上全在复位的时候置1。笔记本电脑的EC监视开机
45. 原来一个lock_page竟然有那么多需要注意和学习的地方,sync_page和writepage的不同在于,前者直接和底层存储设备联系,将数据回写到磁盘,而后者只是将数据回写请求挂在了设备的请求队列等待磁盘的io调度,注意状态机的变化,在调用writepage之前要清除dirty标志, 调用完成后要设置writeback标志,清除lock标志。
46.lock_page也是一个非常值得一读的函数,如下:
static inline void lock_page(struct page *page)
{
might_sleep();
if (TestSetPageLocked(page))
__lock_page(page);
}
might_sleep() 是个抢占点,接下来的调用走到了__wait_on_bit_lock,它和__wait_on_bit是有区别的,前者用的是 test_and_set,后者用的是test,区别在于,test_and_set无论如何都要将标志位置为1,然后返回原来的值,而test则仅仅返 回当前的值,这就是为何么__wait_on_bit_lock加上lock后缀的原因,它就是为了设置一个标志而等待的,如果别人在它等待期间清除了标志,那么test_and_set就返回0,退出等待,这样就合并了一步操作,要注意的是,必须是共享标志才能这么干,相信作者一开始的时候准备用 page lock这个机制防止对page io的重入
47.wait_on_inode也是很有意思的啊!另外在创建超极快的时候,可以创建唯一的single超极块
48.中断栈的使用使得内核不必一下子为每个进程分配一个2页的不可换出的内核栈,从而减轻了内存压力,以下代码做了实际的事情
#ifdef CONFIG_4KSTACKS
curctx = (union irq_ctx *) current_thread_info();
irqctx = hardirq_ctx[smp_processor_id()];
if (curctx != irqctx) {
int arg1, arg2, bx;
isp = (u32*) ((char*)irqctx + sizeof(*irqctx));
irqctx->tinfo.task = curctx->tinfo.task;
irqctx->tinfo.previous_esp = current_stack_pointer;
irqctx->tinfo.preempt_count =
(irqctx->tinfo.preempt_count & ~SOFTIRQ_MASK) |
(curctx->tinfo.preempt_count & SOFTIRQ_MASK);
asm volatile(
" xchgl %%ebx,%%esp /n"
" call *%%edi /n"
" movl %%ebx,%%esp /n"
: "=a" (arg1), "=d" (arg2), "=b" (bx)
: "" (irq), "1" (desc), "2" (isp),
"D" (desc->handle_irq)
: "memory", "cc", "ecx"
);
} else
#endif
desc->handle_irq(irq, desc);
49.sys_sched_yield可以放弃现在的进程,然后让内核有调度别的进程的机会
50.中断在2.6.25.8里面被线程化了,系统为每一个中断注册一个中断线程,然后在有中断来临的时候将之唤醒:
int redirect_hardirq(struct irq_desc *desc)
{
if (!hardirq_preemption || (desc->status & IRQ_NODELAY) ||!desc->thread)
return 0;
#ifdef __i386__
if (debug_direct_keyboard && (desc - irq_desc == 1))
return 0;
#endif
BUG_ON(!irqs_disabled());
if (desc->thread && desc->thread->state != TASK_RUNNING)
wake_up_process(desc->thread);
return 1;
}
51.splice和tee系统调用改变了以往的sendfile的实现方法,把原来的文件直接拷贝该为了通过一个pipe间接的拷贝完成
52.shrink_slab可以压缩slab,通过一个链表shrinker_list调用之上的压缩回调函数,比如压缩dcache的就是shrink_dcache_memory,它从dcache的lru链表中取出一个释放掉。以下说一下dcache:
每个dentry对象都属于下列几种状态之一:
(1)未使用(unused)状态:该dentry对象的引用计数d_count的值为0,但其d_inode指针仍然指向相关的的索引节点。该目录项仍然包含有效的信息,只是当前没有人引用他。这种dentry对象在回收内存时可能会被释放。
(2)正在使用(inuse)状态:处于该状态下的dentry对象的引用计数d_count大于0,且其d_inode指向相关的inode对象。这种dentry对象不能被释放。
(3)负(negative)状态:与目录项相关的inode对象不复存在(相应的磁盘索引节点可能已经被删除),dentry对象的 d_inode指针为NULL。但这种dentry对象仍然保存在dcache中,以便后续对同一文件名的查找能够快速完成。这种dentry对象在回收内存时将首先被释放。
Linux为了提高目录项对象的处理效率,设计与实现了目录项高速缓存(dentry cache,简称dcache),它主要由两个数据结构组成:
1. 哈希链表dentry_hashtable:dcache中的所有dentry对象都通过d_hash指针域链到相应的dentry哈希链表中。
2. 未使用的dentry对象链表dentry_unused:dcache中所有处于“unused”状态和“negative”状态的dentry对象都通过其d_lru指针域链入dentry_unused链表中。该链表也称为LRU链表。
但是dcache是在什么情况下被归还给系统的呢?我是个决定论者(宿命论者?),一切的结果在事物的初始阶段就设置好了,那么在dcache_init里面有个调用set_shrinker(DEFAULT_SEEKS, shrink_dcache_memory),而在shirink_slab里面就是遍历shrinker链表,然后依次调用set操作中设置的回调函数实现回收,至于shrink_slab是怎么回事,不说了,简单!
53.突然想起了浮点处理器和浮点数格式
54.图灵停机问题-哲学问题
55.tcp的syncookie计算方法问题
56.packet 和raw套接字不是一个概念,前者可以操作以太数据,而后者只是ip数据。进一步通过linux分析代码得知,网卡通过比较硬件地址和帧地址然后丢弃不是发给本网卡的帧,这是在网络层作的,就是ip_rcv,这样做不是高效的,因为这是在软中断里面执行的,而且又要占用skb队列,但是好处就是我们可以嗅 探任意发给我们的帧。
57.1.HASH表的长度是可变的,当表长达到一个限定值时,将重建这个HASH表,被免出现HASH冲突表过长造成查找效率降低。
2.终于知道了linux中的radix树的算法。
3.bsd系统里的radix路由表算法
58.abi定义了运行时的兼容性问题,这个问题是api无法解决的。api所能解决的是静态状态下的兼容性问题
59.windows的消息驱动:系统消息队列和线程消息队列以及窗口函数。我发现x window的做法更好,通过网络传输,而且和系统内核没有任何关系,完美的实现了windows上同样的功能(通过strace命令可以查到x系统的调用)(效率问题另算)
60.linux中断的面向对象类图
61.rc0寄存器的wp位
62.红黑树和AVL树的比较。实际上红黑树的最高高度要小于avl树,所以保证了最坏性能好于avl树,另外就是旋转操作,它的它的统计性能要好于平衡二叉树,毕竟现实当中没有那么多真正理想中的平衡需求.splay tree就是缓存树
63.哈希表在linux内核当中的应用十分广泛,pid,路由,dcache,socket等都用哈希,bsd中用的最多的就是树了,上面的splay树就是bsd中的树,主要链接虚拟内核空间。pid的哈希结构。哈希的冲突解决的方法.prio_tree树的反向映射
64. 超线程的性能下降是频率很高的排空共享的缓存导致的,另外一个原因就是调度的不利影响,比如nt系统的调度程序就可能把两个线程调度到同一个处理器的两个不同的逻辑处理器里,很显然,linux没有这样的问题,dependent_sleeper( )函数。一般情况下,该函数立即返回0,但是假如内核支持超线程技术,该函数检查将被运行的进程是否有比已运行在同一个物理CPU上一个逻辑CPU上的兄 弟进程的优先级低。假如是,schedule拒绝选择低优先级进程,而是执行swapper进程。
65.linux的电梯算法,可以扩展之,分别称为cfq,as,deadline,noop等,避免了饥饿。同时复习了qos的树形结构算法,三个概念:排队规则,类,过滤器,另外就是优先级继承和优先级置顶(pip和pcp)
66.细粒度多线程在每个时钟周期都要切换线程,而粗粒度多线程一直运行一个线程直到遇到阻塞才切换
67.用户线程的upcall框架,可以模拟硬件中断,另外用户线程和内核线程的多路复用也可以用upcall,use_mm可以施加到一个专门为一个带有若干用户级线程的进程上,为之创建若干虚拟处理器,为了并行的运行用户线程
68.两种最短路经的求法/dio只尝试一次,如果一次没有将数据写完,则用bufferd io代替,但是为了符合语义,则等待同步返回以后再返回用户空间,这样是因为将繁琐的处理交给内核
69.solaris 的容器技术实现了操作系统级别的虚拟化,为应用提供了一个操作系统的抽象。numa整合了smp和mpp的优势,smp运行一个操作系统实例,但是由于总线竞争因素,扩展性不好,而mpp运行n个操作系统实例,可扩展性好,而numa运行一个实例,可扩展性又好
70.solaris采用了多级调度,分别作用于zone,project,task,process,这样很适合大规模的应用。fss调度类一定好好体会
71. 今天刚知道unix的传统调度法,原来这么猛,无知的我还一直沉湎于linux的方法呢,比如O(1),我觉得就连当今的cfs都无法与unix匹敌,事 实上windows的调度方法也不错,肯定模仿了unix,就看他那么多优先级提升就看得出,但是还是感觉很乱。另外linux调度中,当进程被唤醒的时候,在o(1)法中,优先级也是重新计算的,而且在cfs中,基本上也可以保证io进程被唤醒之后首先被执行
72.linux中内存都是 从伙伴系统得到的,为了防止内部碎片,每个cpu都保存了一个单页池(冷,暖),为诸如vmalloc之类的要求物理地址不必连续但虚拟地址连续的虚拟服务,如果这个池不够了,则一次性从伙伴系统卸下一批备用。另外在2.6的内核里面伙伴系统已经不再使用位图了
73.san存储网络
74. 页面的分配和管理是一个相当频繁的操作, 所以2.6内核做了大量的工作来减小相关的锁的粒度, 以及锁占用的时间, 例如 Per-CPU page list的使用减少了分配内存时请求锁的次数,而使用 pagevec结构批量处理页面, 使得核心在管理inactive, active LRU链表的时候能够较短时间的占用锁(可以将链表页面保持在一个范围内部,而实际上pagevec就是一个批量的页面收集装置)///基树可以很好得取 代全局散列表,对锁的争用减少,而且其中的两个tag字段设计的非常巧妙。
75.__pagevec_release中调用lru_add_drain是为了将原来的收集加入链表,然后就可以一视同仁的进行回收了。
76.每个cpu都有一个pcp,内含两个链表,一个热链一个冷链,如果是cpu使用的,则高速缓存可能还有,那么放入热链,如果是dma之类的使用,则不使用高速缓存,那么放入冷链
77. 每个节点一个kswapd线程;pagevec机制(冷页面队列)减少对锁的争用;oom_killer从kswapd线程转移到分配器的调用者 上;all_unreclaimable逻辑防止扫描风暴;O(1)的objrmap反向映射取代了swap_out();swappiness调整交换 进程内存与交换page cache的平衡;swap token防止抖动;不直接在LRU队列上操作,而是先转移到临时队列,操作完后再转回LRU队列,减少了锁的持有时间;去掉了page的老化机制;
78.hp的虚拟分区有两种,一个是vPAR,还有一个是Integrity VM,前者提供独立的硬件设备划分,而后者完全虚拟化,硬件是共享的,所以不需要修改操作系统就可以,而前者必须要操作系统支持这么猛的硬件特性,比如,完全硬件资源划分
79.超级计算机可以是向量机,而不是标量机,标量机可以通过超流水线,超长指令字,超标量来支持指令级并行。通过指令级并行,好的算法和功能部件以及提高工作主频来提高处理机性能,而向量机则是通过并行技术来计算向量的分量的
80.垂直浪费和水平浪费
81. 理解了cpu在启动时的层次关系,比如node->phys cpu->cpu core->smt cpu,这就是新内核中的调度域和域中的调度组,昨晚明白了每个cpu(包括逻辑cpu)上都有一个idle进程,初始化的时候开始运行,从而启动各个 cpu
82.linux从2.6.18内核开始用mutex_rt来支持优先级继承协议,分别通过两个链表来实现,一个和资源关联,代表等待这资源的进程,另一个和关联,代表等待这个进程释放资源的进程,不一定是一个资源,这在一个进程拥有很多资源的时候很有用,每次进程释放一个资源的时 候,唤醒的总是等待所有当前进程拥有资源的等待队列里的最高优先级的进程,解决了跨资源竞争资源的炯面
83.从linux优先级继承协议中学习了plist,一个优先级的有序链表,linux内核里面的数据结构是非常有意思的
84.http_load的代码是用select实现的,又看了sys_select的实现
85. 看了tcp的接受队列的实现,三个队列(重点:后备队列),如果套接字被锁,则放入后备队列,在套接字被释放的时候处理后备队列的数据报,如果是状态已经就绪的套接字,那么就可以先放入prequeue中(以便直接向进程拷贝),这时进程上下文中就可以直接将prequeue中的数据拷贝到进程,否则进入 慢速模式,tcp_recvmsg的进程被唤醒之后开始拷贝receive_queue中的数据报
86.安装了loadrunner软件,进行了一个对IIS服务器的测试,看来这款软件真的很不错的
87.读了linux2.6.26内核nfs的实现,将以前的nfsiod换成了工作队列,实现上好了很多,特别是调度状态机的转换。SUN的rpc调用目前采用三元组来识别远程过程,在linux下的实现是非常对称的
88. 最新的linux内核2.6.27(2008/10/13)中,get_user_pages的逻辑起了变化,因为以往情况get_user_pages 的调用之前都要down_read(current->mm->mmap_sem),如果有两个进程操作同一个地址空间(线程的情况),那么一个竞态就出现了,所以在新内核里面为了更加适应多处理器的情况,就不再每次使用get_user_pages的时候都请求信号量读写锁了,而只是看看需要get的pages是否已经在内存中了,如果在,就仅仅增加它的引用计数就可以了,这个函数就是get_user_pages_fast。
89.synchronize_rcu和rcu_barrier的区别。前者是针对特定一个,后者是等待所有未决的rcu完成
90.无锁的page cache就是应用了rcu锁,而且加入了很多判断
91.smt的取指逻辑,也是一个策略问题,在多个线程间进行取指调度
92.iis的工作进程架构和 工作进程回收理论,感觉很ugly,还有什么脚本映射之类的,更恶!
93.逻辑哲学论(维特根斯坦)
94.包含所有集合的那个集合,是否是自身的真子集?无论你回答是或否,都不对。
95.0型文法,对应短语结构语言;1型文法,对应上下文相关语言;2型文法,对应上下文无关语言;3型文法,对应正则语言。其中每一个都是前一个的真子集
96.《查拉图斯特拉如是说》一书中有句极其恶毒的话:“你去女人那里吗?别忘了你的鞭子。”
97.(摘录,出处忘记)一、近现代科学有几个基本元素的本质解释不清:时间、质量(能量)、电(磁)。
现有的定义都是说它们是事物的“固有属性”、“内稟属性”云云,从不解释它们“是什么”。我们对它们的定义都是对于它们表现形式的描述。
在此基础上,我们对它们之间的关系进行刻画,得到某种程度上近似正确的关系式,这就是所谓的公式。
这些公式所阐述的关系,在我们力所能及的条件下,都能重现,于是被用于指导生产实践,甚至被包括大部分科学家在内的绝大部分人类视为客观
真理。
“科学”就是上述这些东西的代号。
二、科学与宗教的不同之处在于:科学可以重现,宗教不能。
重现,这很重要。在不同的生产力水平下,人类科学的表现形式可能差异很大,但是科学的标准就一条:能否重现从而验证。大致说来,先进的生
产力对应先进的科学水平。
三、经济、人文和哲学。
前两者是定性的科学,基本还没有定量(即便有公式,也还很粗糙),重现难度较高。哲学是什么,还很难讲,有点像lz所说的宗教(我的理解:
lz所说的宗教,是指人类对于自然和自身的解释)。
四、科学本身不是宗教,但是打着科学的旗号干“世俗宗教”的事情,这是有的。
西方的科学是先进,生产力是先进。但这不表示其生活理念、处世哲学、社会制度、生产关系等等也是先进的。现在有人试图将这些东西混淆,这就是“打着科学的旗号干世俗宗教的事情”了
98.操作系统以及数据库理论(以及xxx理论)中的三大问题(算法):对于数据库互斥,应用读者-写者问题;对于IO以及进程同步,应用哲学家就餐问题;对于cs模式进程同步,应用理发师问题