Mar
27
注:以下测试都是在Ubuntu 9.10 + Gcc 4.4下测试。
1.c
2.c
说明如果没有return语句,那么返回值应该是不确定的。
3.c
增加一个程序test.c
分别运行1.c 2.c 3.c编译后的可执行程序,可以发现,1.exe的返回值是不确定的,但末2位都是0; 2.exe的返回值总是0; 3.exe的返回值总是0 。如果修改2.c的return 0为return 1或2,又或者修改3.c里面的 $0 为 $1 或者 $2 ,可以发现返回值就变成了 100 和 200。这说明在x86下,主函数结束后会将返回值存放在EAX这个寄存器中。
1.c
int main(){}
$ gcc -S 1.c .file "1.c"
.text
.globl main
.type main, @function
main:
pushl %ebp
movl %esp, %ebp
popl %ebp
ret
.size main, .-main
.ident "GCC: (Ubuntu 4.4.1-4ubuntu9) 4.4.1"
.section .note.GNU-stack,"",@progbits
.text
.globl main
.type main, @function
main:
pushl %ebp
movl %esp, %ebp
popl %ebp
ret
.size main, .-main
.ident "GCC: (Ubuntu 4.4.1-4ubuntu9) 4.4.1"
.section .note.GNU-stack,"",@progbits
2.c
int main(){ return 0; }
$ gcc -S 2.c .file "2.c"
.text
.globl main
.type main, @function
main:
pushl %ebp
movl %esp, %ebp
movl $0, %eax
popl %ebp
ret
.size main, .-main
.ident "GCC: (Ubuntu 4.4.1-4ubuntu9) 4.4.1"
.section .note.GNU-stack,"",@progbits
.text
.globl main
.type main, @function
main:
pushl %ebp
movl %esp, %ebp
movl $0, %eax
popl %ebp
ret
.size main, .-main
.ident "GCC: (Ubuntu 4.4.1-4ubuntu9) 4.4.1"
.section .note.GNU-stack,"",@progbits
说明如果没有return语句,那么返回值应该是不确定的。
3.c
int main() {__asm__("movl $0, %eax"); }
增加一个程序test.c
#include <stdio.h>
#include <stdlib.h>
int main()
{
int s = system("./1.exe");
printf("return: %x\n", s); //16进制输出
return 0;
}
#include <stdlib.h>
int main()
{
int s = system("./1.exe");
printf("return: %x\n", s); //16进制输出
return 0;
}
分别运行1.c 2.c 3.c编译后的可执行程序,可以发现,1.exe的返回值是不确定的,但末2位都是0; 2.exe的返回值总是0; 3.exe的返回值总是0 。如果修改2.c的return 0为return 1或2,又或者修改3.c里面的 $0 为 $1 或者 $2 ,可以发现返回值就变成了 100 和 200。这说明在x86下,主函数结束后会将返回值存放在EAX这个寄存器中。
Mar
26
php用fsockopen打开的fp是行缓冲的, 想要数据立即发送到服务器, 就在每次fwrite的数据后面加一个\n。
php的fwrite是atomic的。
java的wait()和notify()是任何对象(基本数据类型不行)都可以用的, 因为每个对象都有一个锁。在针对对象x的时候, 必须处于synchronized(x){}代码段内使用,否则会抛出一个 IllegalMonitorStateException: Thrown to indicate that a thread has attempted to wait on an object's monitor or to notify other threads waiting on an object's monitor without owning the specified monitor.
java的finalize不是析构函数, 只有gc运行起来的时候才可能会调用到它, 而且还不能继承。不能完全依赖它来作一些对象结束时本该作的事情。比较靠谱但是又比较丑陋的是用try-catch-finally来完成。
在linux下如果先chroot再getpwnam失败, 很可能是因为chroot以后就找不到/etc/passwd了。TODO chroot以后无法调用可执行程序的问题还需要再了解一下原因。
WIFEXITED/WIFSIGNALED等宏的详细说明在man 2 wait里面。
ptrace捕获到的每个syscall大部分都有进和出2次;除了execve, 只有一次。
用这个命令来计算代码行数。@3-25目前的结果是4741行。
php的fwrite是atomic的。
java的wait()和notify()是任何对象(基本数据类型不行)都可以用的, 因为每个对象都有一个锁。在针对对象x的时候, 必须处于synchronized(x){}代码段内使用,否则会抛出一个 IllegalMonitorStateException: Thrown to indicate that a thread has attempted to wait on an object's monitor or to notify other threads waiting on an object's monitor without owning the specified monitor.
java的finalize不是析构函数, 只有gc运行起来的时候才可能会调用到它, 而且还不能继承。不能完全依赖它来作一些对象结束时本该作的事情。比较靠谱但是又比较丑陋的是用try-catch-finally来完成。
在linux下如果先chroot再getpwnam失败, 很可能是因为chroot以后就找不到/etc/passwd了。TODO chroot以后无法调用可执行程序的问题还需要再了解一下原因。
WIFEXITED/WIFSIGNALED等宏的详细说明在man 2 wait里面。
ptrace捕获到的每个syscall大部分都有进和出2次;除了execve, 只有一次。
用这个命令来计算代码行数。@3-25目前的结果是4741行。
引用
find -regex ".*\.\(java\|cpp\|c\|h\|sh\|css\|js\|php\)" -exec wc -l {} \; | awk '{sum+=$1}END{print sum}'
Mar
22
就是前面那个 c/c++版 logger.h 到php的移植。使用基本一致。
代码详见: http://code.google.com/p/woj-land/source/browse/trunk/code/web/lib/logger.lib.php
另附针对此日志格式的php写的查看工具:
http://code.google.com/p/woj-land/source/browse/trunk/tools/logviewer/
代码详见: http://code.google.com/p/woj-land/source/browse/trunk/code/web/lib/logger.lib.php
另附针对此日志格式的php写的查看工具:
http://code.google.com/p/woj-land/source/browse/trunk/tools/logviewer/
Mar
10
LOGGER v0.0.3
A simple logger for c/c++ under linux, multiprocess-safe
---- CopyLeft by Felix021 @ http://www.felix021.com ----
一个最简单的使用这个日志系统的程序:
@ 2010-03-22 p.s. 增加了php移植版
A simple logger for c/c++ under linux, multiprocess-safe
---- CopyLeft by Felix021 @ http://www.felix021.com ----
一个最简单的使用这个日志系统的程序:
#include "logger.h"
int main()
{
log_open("log.txt");
log_add_info("id:1001");
FM_LOG_DEBUG("test %d", 123);
return 0;
}
记录日志内容为:int main()
{
log_open("log.txt");
log_add_info("id:1001");
FM_LOG_DEBUG("test %d", 123);
return 0;
}
引用
--NOTICE-- [2010-03-10 18:10:18] [logger.h:91] log_open
--DEBUG-- [2010-03-10 18:10:18] [main.c:7] [id:1001] test 123
--NOTICE-- [2010-03-10 18:10:18] [logger.h:99] [id:1001] log_close
--DEBUG-- [2010-03-10 18:10:18] [main.c:7] [id:1001] test 123
--NOTICE-- [2010-03-10 18:10:18] [logger.h:99] [id:1001] log_close
下载文件 (已下载 1905 次)
@ 2010-03-22 p.s. 增加了php移植版
Mar
8
zz from http://bbs.sysu.edu.cn/bbstcon?board=CS&file=M.1267951351.A
发信人: kyhpudding (只要衫除实得~), 信区: CS
标 题: IT 民工男的 CS 课程记忆
发信站: 逸仙时空 Yat-Sen Channel (Sun Mar 7 16:42:31 2010), 转信
先介绍下自己, 03CS 本科
在某更懂中文的地方混了两年多, 做社区产品, 后来做基础平台
带项目带新人前端到后端应用到底层跟各部门死磕无处不折腾
每年都为可以公费回广东回来校招, 据说是杀手, 不过我不觉得
最近在一以企鹅为吉祥物的公司继续折腾
此文仅代表个人观点, 也只包含个人经验
聊聊 CS 本科各种课程对实际工程工作,
更准确点, 对典型互联网行业的工程工作的影响
试图回答: 这些课程有啥用? 以及, 为啥面试会问这种 BT 问题?
不过如果你不希望走技术方向, 或者希望折腾一下技术就"转管理"
请忽略这篇文章
首先是数学, 我本科四年最后悔的事就是没把数学学好. 掩面, 这个问题先不谈.
程序设计, 首先是语言问题. 可能大家会抱怨出来工作基本都是 java C# 了, 为毛
大学还在教 C++, 落后! 好吧, 我最熟悉的语言其实是 C 语言......
我们看程序设计担负的任务. 一方面, 你必须掌握一门跟计算机沟通的语言, 否则后面
的课根本没法学. 另一方面, 通过学习程序设计 --- 而不是某一门特定语言, 掌握一些
基础的设计方法和一些思路, 为进行真正的工程开发做准备.
从掌握计算机原理, 以有效利用计算机的角度考虑, 应该选一门相对低级的高级语言,
这自然是 C, 它对于一些底层问题: 硬件, 数据结构, 底层操作系统机制等
提供了合适程度的抽象, 把我们对计算机的认识从底至上衔接起来: 写汇编时, 你得知道
指令对底层硬件的意义; 同样的, 你需要能把 C 的循环, 数组寻址, 指针在汇编上
到底是什么解释清楚, 你需要知道函数调用压栈的到底是什么数据, memcpy 到底怎么
拷的数据 (经典问题). 到学 OS 时, 如果用 linux (或任何 UNIX-like) 做教材样本,
你得有很扎实的 C 语言功底, 才做得来操作系统实验, 或者至少理解系统调用用怎么
完成. C 是系统底层的标准语言, 扎实的 C 语言基础是了解系统底层原理的
敲门砖, 至于为什么要对这些计算机系统底层如此了解的原因, 我们下面再谈.
另一方面的任务, 涉及到许多人每天的工作 --- 程序设计. 两个分支: 数据结构和算法,
软件设计范式, 抽象, 建模现实世界问题, 提供计算机解决. 这要求有一个能让底层细节
不会阻碍思考, 而且相对实用的语言. 越来越多的大学使用 Java, 当然也有不少人讨厌
这个, MIT 使用 scheme 和 python. 从达到教学要求角度看, 我觉得都没什么问题.
前提就是: 你依然得有很好的 C 语言和其他底层知识基础. 数据结构和算法下面我们
还会说到. 设计范式, 抽象, 建模等问题, 相当地困难 (数据结构也是一种抽象方法).
我那时的程序设计书好像就是讲了一堆 C 的知识, 然后后面附加讲了点 "面向对象设计",
其实是在讲 C++ 的语言特性, 非常生硬难懂. 我觉得首先得解决的是一个关于 "如何
抽象问题, 建立模型" 的问题, 而"面向对象" *仅仅是其中一种可选方法*! 而如何使
用语言特性去实现这些抽象方法, 那更是细枝末节. 在这方面, 我还是觉得 MIT 原
6.001 课程 SICP 做得最好, 逐步引导越来越高层的抽象, 一步步教导经典设计思路,
而不是一次过塞给你一坨似是而非的理论以及非常恐怖的语言特性. 至于 design
pattern --- 专指 GoF, 我认为是应该在有相当的开发经验后自行修炼的, 不适宜在
课堂上讲授.
说回来, 我认为程序设计课应该分成两部分: 为了解计算机系统底层原理准备的 C 课程.
以及为学习计算机的高层理论知识提供趁手的高级语言工具. MIT 以前用 scheme,
现在用 python, 两个课程链接:
6.001 SICP
http://ocw.mit.edu/OcwWeb/Electrical-Engineering-and-Computer-Science/6-001Spring-2005/CourseHome/in
dex.htm
6.189, 这门课的教材就叫 How to Think Like a Computer Scientist
http://ocw.mit.edu/OcwWeb/Electrical-Engineering-and-Computer-Science/6-189January--IAP--2008/Course
Home/index.htm
程序设计是一个 *准备* 课程, 好戏在后头. 在实际开发中, 底层我们用 C/C++
应用层我们用 Java PHP Python 等等等等, 还有各种脚本, 甚至自己设计语言. 从语言
角度, 我不认为深入掌握 C 和 Scheme 的人学习任何还算正常的语言会有多难.
至于应用框架/系统, 那是另一个问题, 有兴趣的自行学习, 许多大公司对此自有一套,
大学不是什么培训机构, 要在课堂上讲这些, 会让人笑掉大牙.
数据结构与算法, 这咚咚每天都要跟它打交道. 基础数据结构, 是这行的通用语言. 面试时
要考察 candidate 是否对此熟练掌握, 其重要考虑就是: 不掌握无以沟通. 没人有功夫
跟你解释 B+ 树是怎么回事, 如果我说这个模块维护了个 B+ 树你看着我一面惘然, 那
大家都会很痛苦, That's it. 当然, 有的数据结构, 比如倒排表, 你没听说过我觉得很
正常, 但我可以三言两语就让你明白这是怎么回事, 你可以马上运用它来解决问题, 那就
行了.
算法 --- 参加 ACM 对此有帮助, 但专门钻研算法的奇怪技巧却没太大帮助. 同理, 一些
基础算法, 例如排序, 是行业通用语言, 不掌握无以沟通. 而每个专业分支都会有其专门
的一些算法, 这些也不是本科计算机课程可以和需要教授的, 本来就应该在工作之后再
学习.
但另一方面, 我们往往需要设计算法 --- 往往是某些算法的变体和结合, 我们更往往要
分析算法复杂度 --- 这是个要命问题. 这是可以在课堂上学习到一些基本方法的, 虽然
会令这门课看起来更难, 而且需要更好的数学知识 (知道我为啥后悔了吧, 顺便说一下,
某大牛的观点, CS 数学是应该学数学分析的, 深以为然). 但我认为, 有基础的人就算
不知道某算法, 也会一听就明白, 并能利用. 但算法分析, 这个不抓紧时间在课堂上学
好, 以后就难了.
算法方面还是建议看 Introduction to Algorithms 吧, MIT 课程
http://ocw.mit.edu/OcwWeb/Electrical-Engineering-and-Computer-Science/6-046JFall-2005/CourseHome/ind
ex.htm
微机原理/计组/体系结构. 对我来说, 这些课程的作用就是让我知道, 我折腾的拿个铁
盒子到底是怎么一回事. 考虑一些系统性能问题, 做设计权衡时, 我必须考虑实际的计算
机体系, 各部分的性能状况 --- 有了基础, 还要时刻紧跟随摩尔定律发展的潮流. 我们
必须时常考虑, 硬盘的读写特性是怎样的? Cache 能多有效, 怎么利用多核 etc
操作系统原理, 这是一门核心课程. 在我的工作中, 它有两方面用途. 一方面, 为了实现
高效的低层应用, 我需要清楚操作系统的行为, 需要了解我的 API --- 系统调用的实现
原理, 效率情况. 我这行在服务端通常使用 linux 系统, 而 OS 教学在传统上以 UNIX
为范本, 有的甚至直接采用分析 linux 内核的方法, 这就很好地结合起来了. 基本上,
扎实的 OS 知识, 再加上 APUE, linux 系统编程就问题不大了.
OS 也提供了一些常用的概念和抽象方法: 例如锁, 线程和进程. 你会在各种地方碰到他们
你需要利用它, 你有时候需要自己实现它, 你有时候还会发现一个自旋锁耗掉多少 CPU
指令是影响你的程序性能的关键......
另一方面, 可能是大家容易忽视的, 是 OS 乃一门非常重要的工程入门课 --- 我认为这
才是 OS 最大的意义: 开始学习设计实际系统.
- 学习一个真正的大型系统. 真实的操作系统都非常复杂, 你可以看到现实世界的
模块划分和抽象方法, 你可以看到闪光的设计思想 --- 以及一些丑陋的既成事实, 这
比任何一本所谓 "设计方法" 的书都来得精彩. ps. 看看 APUE 吧.
- 分析瓶颈, 考虑权衡: 当你面对的是一个系统而不是一个单一问题点的时候,
分析瓶颈成了一种重要能力. 没有最优算法的说法, 调度方案等等有得必有失, 方案取舍
必须在充分的分析基础上进行. linux 的调度算法, cache 设计是怎么样并不重要.
重要的是: 它为什么要这么设计? 解决什么问题? 这个方案基于什么假设? 对什么有利
而什么不利? 是否与应用模式相吻合? 我们用什么方法来精确测量, 验证这些问题?
这些都是非常重要的工程能力. 我遇到过一位同学, 解决一个模块的性能问题, 上来
看了一通代码, 然后跟我说: 那个函数复杂度是 O(N^2) 可以优化成 O(NLogN) 的,
但实际上那个函数的数据规模只是几十, 更重要的是, 此时模块的瓶颈在 IO. OS 的课程
教会我们这些重要的分析方法, 还有一些非常精妙的设计思路 --- 这会在应用其他地方
用得着.
网络, 这门课同样有两方面意义. 一方面是掌握常识: 我们总得知道什么叫 "四层设备",
总得能分清楚交换机和路由. 当然, 一些网络编程知识也包含其中. 另一方面, 我认为对
协议设计的理解, 尤其是 TCP 设计的理解, 提供了设计分布式系统的基本思路和基本知
识, TCP 的许多设计方法, 在高层次通讯协议的设计中照样适用. 我在文后会给两个例子.
数据库, 我觉得这门课非常难教. 讲理论吧, 讲成数学了. 讲实现吧, 不现实, 讲 SQL?
这不搞笑么? 实际上我们每样都得学点. 数据库跟 OS 课程很相似的一点是: 它是许多
学科重点知识和问题的集中体现, 要看看那些稀奇古怪的知识是怎么用到现实中的?
看看 OS 和数据库吧.
数据库一方面得讲经典的关系理论 --- 基本上只要还是在设计存储系统, 就很难撇得
开它, 这还得有很好的数学基础. 同时也掌握了基本的范式, 基本的设计方法. 在思考
一个实际问题的存储方案时, 这是你的思考起点. 业界这两年流行讲反范式, 或者干脆
讲 NoSQL, No-RDBMS, 不过相信我, 经典的关系理论往往还是你思考的起点.
数据库总会有个地方讲并发, 讲 ACID, 讲事务. 嘿嘿, 欢迎来到业界第一大坑, OS 的
锁知识学好没? 准备了点分布式系统常识没? 准备好了就跳吧. 业界流行对 ACID 进行
取舍, 以达到可扩展性等目的, 我们不是要盲目去接受这些 "流行" 的东西, 我们有
时间在课堂上好好搞清楚 ACID 各为的是什么? 怎么实现? 会有什么问题? 怎么个死锁法?
最好再来点实现内容, 数据库的 index 是个什么原理? 存储具体该怎么实现? 一个查询
语句, 结合 index, 你可以怎么做?
当然我们还是得知道的 SQL 的, 这东西实在太好懂, 表达工具而已, 抠细节则不必.
我想课堂上自然也不会详细讲 MySQL 怎么配置啊, Oracle 有什么 BT 特性啊之类的
东西.
编译原理, 这门课放在本科承载的内容有点杂了. 首先得讲一下基础中的基础, 自动机.
又得讲经典的词法分析语法分析内容. 还得讲怎么编译到机器语言.
从实用角度来讲. 一方面自动机的知识词法语法分析的知识给我们提供解决相关问题
的基本思路 --- 这些都是 CS 最基础的问题. 另一方面就如一开头所说, 我们有时候
不得不设计语言, 在设计语法, 设计解析器的时候, 了解基本的编译原理知识, 并熟练
运用 lex&yacc 成了必须.
至于代码生成的部分, 我不敢说重要性有多高, 但至少我用到过相关的知识.
软件工程, 恕我直言, 这不是应该在 CS 上讲的课程, 至少不应该看得很重. 这有很多
是管理问题, 又有不断更新的新概念, 新理论. 更重要的, 我认为它更多的是 Art,
而不是 Science, 更应该在实际工作中学习积累, 做成选修课不好?
反正放心吧, 无论讲不讲, 你铁定不会一出来就是项目经理的.
我还要推荐 joelonsoftware 的一篇著名文章
Advice for Computer Science College Students
http://joelonsoftware.com/articles/CollegeAdvice.html
最后, 这里提供几个问题, 帮助大家检查一下, 自己的本科学习是否牢固,
以支撑工程需要. 这全部是基本问题, 算法问题就不列了
这不是面试经验, 每个公司的面试都有不同风格,
但解决以下这些问题的能力在我的工作中是必要的.
1. 请实现 memcpy
2. 用 PV 信号量或 mutex, 实现一个读写锁
3. 说说 fread 从一开始到读到磁盘的整个调用过程?
4. malloc 是操作系统内核实现的吗? 实现一对 malloc/free
5. 说说 TCP 三次握手? 为什么是三次? 为什么关闭连接要来四次? SYN Flodd 怎么弄,
怎么预防?
6. 说说 TCP 的滑动窗口机制, 自己实现一下.
7. 设计一个内存垃圾回收方法, 说说它的优势和局限.
8. 假设我已经有一个 B+ 树的存储实现. 请利用它实现一个基本的数据库系统: 针对
某类查询, 如何建 index, 如何执行查询, 如何完成一条更新操作?
补一门 MIT 的工程课, 建议所有希望投入到工程的同学学习
Computer System Engineering
http://ocw.mit.edu/OcwWeb/Electrical-Engineering-and-Computer-Science/6-033Spring-2009/CourseHome/in
dex.htm
本科的时间, 不花在学习课程上, 去学习某样流行的技术, 也许能令你找到一份令人
羡慕的工作, 但是别怪我乌鸦嘴, 你很快会是那个抱怨知识更新太快, 跟不上,
年纪大了失去竞争力的人.
--
Just for fun
※ 来源:.逸仙时空 Yat-Sen Channel argo.sysu.edu.cn.[FROM: 112.94.249.26]
※ 修改:.kyhpudding 于 Mar 7 18:40:18 修改本文.[FROM: 112.94.249.26]
发信人: kyhpudding (只要衫除实得~), 信区: CS
标 题: IT 民工男的 CS 课程记忆
发信站: 逸仙时空 Yat-Sen Channel (Sun Mar 7 16:42:31 2010), 转信
先介绍下自己, 03CS 本科
在某更懂中文的地方混了两年多, 做社区产品, 后来做基础平台
带项目带新人前端到后端应用到底层跟各部门死磕无处不折腾
每年都为可以公费回广东回来校招, 据说是杀手, 不过我不觉得
最近在一以企鹅为吉祥物的公司继续折腾
此文仅代表个人观点, 也只包含个人经验
聊聊 CS 本科各种课程对实际工程工作,
更准确点, 对典型互联网行业的工程工作的影响
试图回答: 这些课程有啥用? 以及, 为啥面试会问这种 BT 问题?
不过如果你不希望走技术方向, 或者希望折腾一下技术就"转管理"
请忽略这篇文章
首先是数学, 我本科四年最后悔的事就是没把数学学好. 掩面, 这个问题先不谈.
程序设计, 首先是语言问题. 可能大家会抱怨出来工作基本都是 java C# 了, 为毛
大学还在教 C++, 落后! 好吧, 我最熟悉的语言其实是 C 语言......
我们看程序设计担负的任务. 一方面, 你必须掌握一门跟计算机沟通的语言, 否则后面
的课根本没法学. 另一方面, 通过学习程序设计 --- 而不是某一门特定语言, 掌握一些
基础的设计方法和一些思路, 为进行真正的工程开发做准备.
从掌握计算机原理, 以有效利用计算机的角度考虑, 应该选一门相对低级的高级语言,
这自然是 C, 它对于一些底层问题: 硬件, 数据结构, 底层操作系统机制等
提供了合适程度的抽象, 把我们对计算机的认识从底至上衔接起来: 写汇编时, 你得知道
指令对底层硬件的意义; 同样的, 你需要能把 C 的循环, 数组寻址, 指针在汇编上
到底是什么解释清楚, 你需要知道函数调用压栈的到底是什么数据, memcpy 到底怎么
拷的数据 (经典问题). 到学 OS 时, 如果用 linux (或任何 UNIX-like) 做教材样本,
你得有很扎实的 C 语言功底, 才做得来操作系统实验, 或者至少理解系统调用用怎么
完成. C 是系统底层的标准语言, 扎实的 C 语言基础是了解系统底层原理的
敲门砖, 至于为什么要对这些计算机系统底层如此了解的原因, 我们下面再谈.
另一方面的任务, 涉及到许多人每天的工作 --- 程序设计. 两个分支: 数据结构和算法,
软件设计范式, 抽象, 建模现实世界问题, 提供计算机解决. 这要求有一个能让底层细节
不会阻碍思考, 而且相对实用的语言. 越来越多的大学使用 Java, 当然也有不少人讨厌
这个, MIT 使用 scheme 和 python. 从达到教学要求角度看, 我觉得都没什么问题.
前提就是: 你依然得有很好的 C 语言和其他底层知识基础. 数据结构和算法下面我们
还会说到. 设计范式, 抽象, 建模等问题, 相当地困难 (数据结构也是一种抽象方法).
我那时的程序设计书好像就是讲了一堆 C 的知识, 然后后面附加讲了点 "面向对象设计",
其实是在讲 C++ 的语言特性, 非常生硬难懂. 我觉得首先得解决的是一个关于 "如何
抽象问题, 建立模型" 的问题, 而"面向对象" *仅仅是其中一种可选方法*! 而如何使
用语言特性去实现这些抽象方法, 那更是细枝末节. 在这方面, 我还是觉得 MIT 原
6.001 课程 SICP 做得最好, 逐步引导越来越高层的抽象, 一步步教导经典设计思路,
而不是一次过塞给你一坨似是而非的理论以及非常恐怖的语言特性. 至于 design
pattern --- 专指 GoF, 我认为是应该在有相当的开发经验后自行修炼的, 不适宜在
课堂上讲授.
说回来, 我认为程序设计课应该分成两部分: 为了解计算机系统底层原理准备的 C 课程.
以及为学习计算机的高层理论知识提供趁手的高级语言工具. MIT 以前用 scheme,
现在用 python, 两个课程链接:
6.001 SICP
http://ocw.mit.edu/OcwWeb/Electrical-Engineering-and-Computer-Science/6-001Spring-2005/CourseHome/in
dex.htm
6.189, 这门课的教材就叫 How to Think Like a Computer Scientist
http://ocw.mit.edu/OcwWeb/Electrical-Engineering-and-Computer-Science/6-189January--IAP--2008/Course
Home/index.htm
程序设计是一个 *准备* 课程, 好戏在后头. 在实际开发中, 底层我们用 C/C++
应用层我们用 Java PHP Python 等等等等, 还有各种脚本, 甚至自己设计语言. 从语言
角度, 我不认为深入掌握 C 和 Scheme 的人学习任何还算正常的语言会有多难.
至于应用框架/系统, 那是另一个问题, 有兴趣的自行学习, 许多大公司对此自有一套,
大学不是什么培训机构, 要在课堂上讲这些, 会让人笑掉大牙.
数据结构与算法, 这咚咚每天都要跟它打交道. 基础数据结构, 是这行的通用语言. 面试时
要考察 candidate 是否对此熟练掌握, 其重要考虑就是: 不掌握无以沟通. 没人有功夫
跟你解释 B+ 树是怎么回事, 如果我说这个模块维护了个 B+ 树你看着我一面惘然, 那
大家都会很痛苦, That's it. 当然, 有的数据结构, 比如倒排表, 你没听说过我觉得很
正常, 但我可以三言两语就让你明白这是怎么回事, 你可以马上运用它来解决问题, 那就
行了.
算法 --- 参加 ACM 对此有帮助, 但专门钻研算法的奇怪技巧却没太大帮助. 同理, 一些
基础算法, 例如排序, 是行业通用语言, 不掌握无以沟通. 而每个专业分支都会有其专门
的一些算法, 这些也不是本科计算机课程可以和需要教授的, 本来就应该在工作之后再
学习.
但另一方面, 我们往往需要设计算法 --- 往往是某些算法的变体和结合, 我们更往往要
分析算法复杂度 --- 这是个要命问题. 这是可以在课堂上学习到一些基本方法的, 虽然
会令这门课看起来更难, 而且需要更好的数学知识 (知道我为啥后悔了吧, 顺便说一下,
某大牛的观点, CS 数学是应该学数学分析的, 深以为然). 但我认为, 有基础的人就算
不知道某算法, 也会一听就明白, 并能利用. 但算法分析, 这个不抓紧时间在课堂上学
好, 以后就难了.
算法方面还是建议看 Introduction to Algorithms 吧, MIT 课程
http://ocw.mit.edu/OcwWeb/Electrical-Engineering-and-Computer-Science/6-046JFall-2005/CourseHome/ind
ex.htm
微机原理/计组/体系结构. 对我来说, 这些课程的作用就是让我知道, 我折腾的拿个铁
盒子到底是怎么一回事. 考虑一些系统性能问题, 做设计权衡时, 我必须考虑实际的计算
机体系, 各部分的性能状况 --- 有了基础, 还要时刻紧跟随摩尔定律发展的潮流. 我们
必须时常考虑, 硬盘的读写特性是怎样的? Cache 能多有效, 怎么利用多核 etc
操作系统原理, 这是一门核心课程. 在我的工作中, 它有两方面用途. 一方面, 为了实现
高效的低层应用, 我需要清楚操作系统的行为, 需要了解我的 API --- 系统调用的实现
原理, 效率情况. 我这行在服务端通常使用 linux 系统, 而 OS 教学在传统上以 UNIX
为范本, 有的甚至直接采用分析 linux 内核的方法, 这就很好地结合起来了. 基本上,
扎实的 OS 知识, 再加上 APUE, linux 系统编程就问题不大了.
OS 也提供了一些常用的概念和抽象方法: 例如锁, 线程和进程. 你会在各种地方碰到他们
你需要利用它, 你有时候需要自己实现它, 你有时候还会发现一个自旋锁耗掉多少 CPU
指令是影响你的程序性能的关键......
另一方面, 可能是大家容易忽视的, 是 OS 乃一门非常重要的工程入门课 --- 我认为这
才是 OS 最大的意义: 开始学习设计实际系统.
- 学习一个真正的大型系统. 真实的操作系统都非常复杂, 你可以看到现实世界的
模块划分和抽象方法, 你可以看到闪光的设计思想 --- 以及一些丑陋的既成事实, 这
比任何一本所谓 "设计方法" 的书都来得精彩. ps. 看看 APUE 吧.
- 分析瓶颈, 考虑权衡: 当你面对的是一个系统而不是一个单一问题点的时候,
分析瓶颈成了一种重要能力. 没有最优算法的说法, 调度方案等等有得必有失, 方案取舍
必须在充分的分析基础上进行. linux 的调度算法, cache 设计是怎么样并不重要.
重要的是: 它为什么要这么设计? 解决什么问题? 这个方案基于什么假设? 对什么有利
而什么不利? 是否与应用模式相吻合? 我们用什么方法来精确测量, 验证这些问题?
这些都是非常重要的工程能力. 我遇到过一位同学, 解决一个模块的性能问题, 上来
看了一通代码, 然后跟我说: 那个函数复杂度是 O(N^2) 可以优化成 O(NLogN) 的,
但实际上那个函数的数据规模只是几十, 更重要的是, 此时模块的瓶颈在 IO. OS 的课程
教会我们这些重要的分析方法, 还有一些非常精妙的设计思路 --- 这会在应用其他地方
用得着.
网络, 这门课同样有两方面意义. 一方面是掌握常识: 我们总得知道什么叫 "四层设备",
总得能分清楚交换机和路由. 当然, 一些网络编程知识也包含其中. 另一方面, 我认为对
协议设计的理解, 尤其是 TCP 设计的理解, 提供了设计分布式系统的基本思路和基本知
识, TCP 的许多设计方法, 在高层次通讯协议的设计中照样适用. 我在文后会给两个例子.
数据库, 我觉得这门课非常难教. 讲理论吧, 讲成数学了. 讲实现吧, 不现实, 讲 SQL?
这不搞笑么? 实际上我们每样都得学点. 数据库跟 OS 课程很相似的一点是: 它是许多
学科重点知识和问题的集中体现, 要看看那些稀奇古怪的知识是怎么用到现实中的?
看看 OS 和数据库吧.
数据库一方面得讲经典的关系理论 --- 基本上只要还是在设计存储系统, 就很难撇得
开它, 这还得有很好的数学基础. 同时也掌握了基本的范式, 基本的设计方法. 在思考
一个实际问题的存储方案时, 这是你的思考起点. 业界这两年流行讲反范式, 或者干脆
讲 NoSQL, No-RDBMS, 不过相信我, 经典的关系理论往往还是你思考的起点.
数据库总会有个地方讲并发, 讲 ACID, 讲事务. 嘿嘿, 欢迎来到业界第一大坑, OS 的
锁知识学好没? 准备了点分布式系统常识没? 准备好了就跳吧. 业界流行对 ACID 进行
取舍, 以达到可扩展性等目的, 我们不是要盲目去接受这些 "流行" 的东西, 我们有
时间在课堂上好好搞清楚 ACID 各为的是什么? 怎么实现? 会有什么问题? 怎么个死锁法?
最好再来点实现内容, 数据库的 index 是个什么原理? 存储具体该怎么实现? 一个查询
语句, 结合 index, 你可以怎么做?
当然我们还是得知道的 SQL 的, 这东西实在太好懂, 表达工具而已, 抠细节则不必.
我想课堂上自然也不会详细讲 MySQL 怎么配置啊, Oracle 有什么 BT 特性啊之类的
东西.
编译原理, 这门课放在本科承载的内容有点杂了. 首先得讲一下基础中的基础, 自动机.
又得讲经典的词法分析语法分析内容. 还得讲怎么编译到机器语言.
从实用角度来讲. 一方面自动机的知识词法语法分析的知识给我们提供解决相关问题
的基本思路 --- 这些都是 CS 最基础的问题. 另一方面就如一开头所说, 我们有时候
不得不设计语言, 在设计语法, 设计解析器的时候, 了解基本的编译原理知识, 并熟练
运用 lex&yacc 成了必须.
至于代码生成的部分, 我不敢说重要性有多高, 但至少我用到过相关的知识.
软件工程, 恕我直言, 这不是应该在 CS 上讲的课程, 至少不应该看得很重. 这有很多
是管理问题, 又有不断更新的新概念, 新理论. 更重要的, 我认为它更多的是 Art,
而不是 Science, 更应该在实际工作中学习积累, 做成选修课不好?
反正放心吧, 无论讲不讲, 你铁定不会一出来就是项目经理的.
我还要推荐 joelonsoftware 的一篇著名文章
Advice for Computer Science College Students
http://joelonsoftware.com/articles/CollegeAdvice.html
最后, 这里提供几个问题, 帮助大家检查一下, 自己的本科学习是否牢固,
以支撑工程需要. 这全部是基本问题, 算法问题就不列了
这不是面试经验, 每个公司的面试都有不同风格,
但解决以下这些问题的能力在我的工作中是必要的.
1. 请实现 memcpy
2. 用 PV 信号量或 mutex, 实现一个读写锁
3. 说说 fread 从一开始到读到磁盘的整个调用过程?
4. malloc 是操作系统内核实现的吗? 实现一对 malloc/free
5. 说说 TCP 三次握手? 为什么是三次? 为什么关闭连接要来四次? SYN Flodd 怎么弄,
怎么预防?
6. 说说 TCP 的滑动窗口机制, 自己实现一下.
7. 设计一个内存垃圾回收方法, 说说它的优势和局限.
8. 假设我已经有一个 B+ 树的存储实现. 请利用它实现一个基本的数据库系统: 针对
某类查询, 如何建 index, 如何执行查询, 如何完成一条更新操作?
补一门 MIT 的工程课, 建议所有希望投入到工程的同学学习
Computer System Engineering
http://ocw.mit.edu/OcwWeb/Electrical-Engineering-and-Computer-Science/6-033Spring-2009/CourseHome/in
dex.htm
本科的时间, 不花在学习课程上, 去学习某样流行的技术, 也许能令你找到一份令人
羡慕的工作, 但是别怪我乌鸦嘴, 你很快会是那个抱怨知识更新太快, 跟不上,
年纪大了失去竞争力的人.
--
Just for fun
※ 来源:.逸仙时空 Yat-Sen Channel argo.sysu.edu.cn.[FROM: 112.94.249.26]
※ 修改:.kyhpudding 于 Mar 7 18:40:18 修改本文.[FROM: 112.94.249.26]
Mar
4
花钱如流水 v0.0.1
By Felix021 @ 2010-03-04
http://www.felix021.com
一个PHP+MySQL的简易支出记录系统,提供一些最基本功能,界面简单,方便手机使用。
安装:随便找一个数据库,导入tbl.sql,然后修改config.php里的相关参数即可使用。
(界面很难看,代码很难看,原则:够用就好。)
By Felix021 @ 2010-03-04
http://www.felix021.com
一个PHP+MySQL的简易支出记录系统,提供一些最基本功能,界面简单,方便手机使用。
安装:随便找一个数据库,导入tbl.sql,然后修改config.php里的相关参数即可使用。
(界面很难看,代码很难看,原则:够用就好。)
下载文件 (已下载 1346 次)
Feb
10
决定了毕设做这个东西。WOJ3.0。
起名Land,不是我自己想出来的,忘了是谁贡献的了。之所以叫做Land,看如下的woj名字的演化就知道原因了:D
noah(v1.0) -> oak(ark?)(v1.1) -> flood(v2.0) -> land(v3.0)
去年暑假还写了个不成器的judge然后就荒了,不过也算是打个基础。
这次要更详细地考虑具体的OJ系统架构了。
前端就apache+php吧。如果有空可以试试加一层lighttpd。需要完成的基本功能就是题目相关(包括统计数据),比赛(虚拟比赛?),站内信,题目讨论,后台管理。模板尽量参考Noah的,保持风格统一。这个是代码量最大的,但是应该不难。主要是要实现容易扩展的架构,使得将来增加新功能比较方便,不再需要重写OJ了。
数据库还是MySQL,比较熟。得有个数据转换工具,把noah的数据转过来。
Daemon可以用java,我给oak重写的那个版本拿来改改就能用。
希望有一个judge wrapper负责数据库相关的处理,让judge只负责judge。看起来用php挺好的。
Judge可以在hustoj和之前那个oj的基础上写一个,不过还得有进一步的拆分。每个语言一个judge,因为编译、执行、监控可能都有较大区别。把判断AC/PE/WA的功能和SPJ的功能也独立出来,由wrapper来组装使用。
可能还需要一个补单的,有可能数据库中存在一些还没有judge并且不会再被自动judge的item。
此外有点想搞一个memcached,减轻在比赛时mysql的负担。
目前想到这些,这两天再仔细考虑考虑,就要动手做了。希望有人多提意见和建议。
p.s. 祈祷这个项目不会烂尾...
起名Land,不是我自己想出来的,忘了是谁贡献的了。之所以叫做Land,看如下的woj名字的演化就知道原因了:D
noah(v1.0) -> oak(ark?)(v1.1) -> flood(v2.0) -> land(v3.0)
去年暑假还写了个不成器的judge然后就荒了,不过也算是打个基础。
这次要更详细地考虑具体的OJ系统架构了。
前端就apache+php吧。如果有空可以试试加一层lighttpd。需要完成的基本功能就是题目相关(包括统计数据),比赛(虚拟比赛?),站内信,题目讨论,后台管理。模板尽量参考Noah的,保持风格统一。这个是代码量最大的,但是应该不难。主要是要实现容易扩展的架构,使得将来增加新功能比较方便,不再需要重写OJ了。
数据库还是MySQL,比较熟。得有个数据转换工具,把noah的数据转过来。
Daemon可以用java,我给oak重写的那个版本拿来改改就能用。
希望有一个judge wrapper负责数据库相关的处理,让judge只负责judge。看起来用php挺好的。
Judge可以在hustoj和之前那个oj的基础上写一个,不过还得有进一步的拆分。每个语言一个judge,因为编译、执行、监控可能都有较大区别。把判断AC/PE/WA的功能和SPJ的功能也独立出来,由wrapper来组装使用。
可能还需要一个补单的,有可能数据库中存在一些还没有judge并且不会再被自动judge的item。
此外有点想搞一个memcached,减轻在比赛时mysql的负担。
目前想到这些,这两天再仔细考虑考虑,就要动手做了。希望有人多提意见和建议。
p.s. 祈祷这个项目不会烂尾...
Feb
9
这几天简单学习了一下jsp的使用(主要是看《jsp开发web应用系统参考书籍》系列pdf),大致做一下记录。
首先是环境,jdk是必须的,服务器我用tomcat,因为以前搞noah/oak的时候整过,熟悉些。具体的配置不赘述了,网上很多,无非是JAVA_HOME CLASSPATH CATALINA_HOME之类的环境变量。此外为了连上mysql,还要去下个jar,比如mysql-connector-java-5.0.8-bin.jar,可以在网上搜到。这个要放在tomcat/shared/lib/下面。当然,也是可以放在jsp的WEB-INF/lib下面,但是这个我没研究过,不太了解细节。
最简单地写JSP,其实和写ASP/PHP很像,把java当成一个面向过程的语言填上去就行了。比如经典的hello world:
因为这里的java和普通的*.java程序不一样,所有有些语句也得变,比如import不能直接用了,必须这么写:
格式为 <%@ page oo="xx" %> 这样的oo和xx有很多个,比如session开关就是通过这种方式控制,详情参考那些pdf。包含文件则用<%@ include file="xxxx" %>这样的格式。
在编写的过程中要获取GET/POST等请求的数据以及客户端IP等信息的时候,可以使用默认import进来的request对象,有getParameter()、getMethod()、getRequestURI()、getRemoteADDR()....等方法。相当于php的$_GET/$_POST/$_SERVER等变量的大杂烩。
要控制输出,比如HTTP Header或者具体的Cookie字段,则使用response对象的addCookie()、addHeader()等方法。
Session,则是使用session对象。但是要先<%@ page session="true" %>开启session。
此外还有一个和ASP同样性质也同名的Application对象。看起来像是抄ASP的。就是一个和服务器同生死的全局变量。
以上就是最简单的jsp开发需要的一些东西了。至少开发一个留言板什么都OK了 :)
至于Java Beans,这个是第六章,我还没看...
首先是环境,jdk是必须的,服务器我用tomcat,因为以前搞noah/oak的时候整过,熟悉些。具体的配置不赘述了,网上很多,无非是JAVA_HOME CLASSPATH CATALINA_HOME之类的环境变量。此外为了连上mysql,还要去下个jar,比如mysql-connector-java-5.0.8-bin.jar,可以在网上搜到。这个要放在tomcat/shared/lib/下面。当然,也是可以放在jsp的WEB-INF/lib下面,但是这个我没研究过,不太了解细节。
最简单地写JSP,其实和写ASP/PHP很像,把java当成一个面向过程的语言填上去就行了。比如经典的hello world:
<html>
<body>
<%
out.println("Hello, world!\n"); //在jsp里输出就用out啦,不是System.out。
%>
</body>
</html>
<body>
<%
out.println("Hello, world!\n"); //在jsp里输出就用out啦,不是System.out。
%>
</body>
</html>
因为这里的java和普通的*.java程序不一样,所有有些语句也得变,比如import不能直接用了,必须这么写:
引用
<%@ page import="java.sql.*" %>
格式为 <%@ page oo="xx" %> 这样的oo和xx有很多个,比如session开关就是通过这种方式控制,详情参考那些pdf。包含文件则用<%@ include file="xxxx" %>这样的格式。
在编写的过程中要获取GET/POST等请求的数据以及客户端IP等信息的时候,可以使用默认import进来的request对象,有getParameter()、getMethod()、getRequestURI()、getRemoteADDR()....等方法。相当于php的$_GET/$_POST/$_SERVER等变量的大杂烩。
要控制输出,比如HTTP Header或者具体的Cookie字段,则使用response对象的addCookie()、addHeader()等方法。
Session,则是使用session对象。但是要先<%@ page session="true" %>开启session。
此外还有一个和ASP同样性质也同名的Application对象。看起来像是抄ASP的。就是一个和服务器同生死的全局变量。
以上就是最简单的jsp开发需要的一些东西了。至少开发一个留言板什么都OK了 :)
至于Java Beans,这个是第六章,我还没看...