A universally accepted distinction between a screw and a bolt does not exist.
In common usage the term screw refers to smaller (less than 1/4 inch) threaded fasteners, especially threaded fasteners with tapered shafts (貌似指会越来越细呈锥形,有点像钉子) and the term bolt refers to larger threaded fasteners that do not have tapered shafts (貌似指柱形,因此有的会在终端配套一个螺母,nut). The term machine screw is commonly used to refer to smaller threaded fasteners that do not have a tapered shaft.
Various methods of distinguishing bolts and screws exist or have existed. These methods conflict at times and can be confusing. Old SAE and USS standards made a distinction between a bolt and a cap screw based on whether a portion of the shaft was un-threaded or not. Cap screws had shafts that were threaded up to the head and bolts had partially threaded shafts (照此标准我们要找的是bolt). Today a bolt that has a completely threaded shaft might be referred to as a tap bolt.
gcc -### - show what GCC would have executed
gcc -v - show what GCC is executing
gcc -g x.c -o x; objdump -S x - show the C and generated assembly code
gcc -E -dM -
gcc -C -E - show pre-processor output, but leave comments intact
gcc -M - show all include file dependencies (for use in Makefiles)
gcc -MM - like above, but ignore system include files
Our group has some machines running the old Red Hat Linux 7.3. The system is too old, but I didn’t want to wipe off the disk to install a new system. Since I have root access on them, I decided to install the Debian system in a chrooted environment.
This is how I did it:
sudo -s
cd /tmp
wget http://http.us.debian.org/debian/pool/main/d/debootstrap/debootstrap_1.0.8_all.deb
ar -x debootstrap_1.0.8_all.deb
cd /
zcat /tmp/data.tar.gz |tar xv
debootstrap –arch i386 sid /debian
mount -t devpts devpts /debian/dev/pts
mount -t tmpfs shm /debian/dev/shm
mount -t proc proc /debian/proc
mount –bind /dev /debian/dev
LC_ALL=C chroot /debian/
陈冲在华盛顿邮报发表了一篇题为Let the Games Go On的文章,说得很好,引用两段如下:
This statement could not be further from reality. For one thing, the Chinese are a proud people. They want freedom and greater rights, but they know they must fight for them from within. They know that no one can grant them freedom and rights from afar. The stigma of Western imperialism and the Opium Wars also remains a strong reminder of the past, and Chinese people do not want their domestic policies to be dictated by outside powers. They also do not want the United States to boycott the opening ceremonies of the Games. The U.S. boycott of the 1980 Games in Moscow and the Soviet boycott of the 1984 Olympics in Los Angeles accomplished nothing. A U.S. boycott of the opening ceremonies in Beijing would be counterproductive for relations between the two countries.
For decades, anti-China human rights groups in Washington have spent millions of dollars denouncing China. To many Chinese, it seems that this lobby is the only voice that’s acceptable or newsworthy in the U.S. media and to the U.S. government. But times are changing. We need to be open-minded and farsighted. We need to make more friends than enemies. Remember what a little ping-pong game did for Sino-U.S. relations in the 1970s? Let’s celebrate the Olympics for what the Games are meant to be — a bridge for friendship, not a playground for politics.
Because China is hosting these Olympics … no boycott is necessary. China is a one-party state and, whenever a one-party state hosts an Olympics, ten year later they’re circling the drain if not already down it. To wit:
昨天 (3/28/2008) RMS来到UVa做题为Free Software in Ethics and in Practice的演讲。主题主要是围绕着GNU和free software movement展开,没有涉及到技术(e.g., Emacs)和法律(e.g., GPLv3)上的细节。与以往我们系的报告不同,这一次的报告特地选在一个很大的教室进行,但还是被感兴趣的老中青三代(faculty、grads、undergrads)占满了。
我们系的chair作为RMS的host先对RMS进行介绍。其中她故意说RMS推动了Linux的发展,RMS立即打断并纠正说应该是GNU/Linux,引来哄堂大笑。chair立即解释说她是故意说错测试RMS的反应:)
RMS作为教主,演讲的功力真的不是盖的。他没有使用幻灯片,而仅仅每隔一段时间低一下头看桌子,估计是演讲提纲。他好像演讲的时候不喜欢穿鞋?还不时的不顾形象的擦鼻子,希望大师不是感冒了。
RMS首先开宗明义,提出software freedom包含四个方面,并就这四个方面花了大部分时间阐述。给予用户自由使用和发布软件的自由,使得他们不受限于license,这在道德方面有着积极的意义。否则,当一个用户被朋友要求分享一个程序时,用户就会面临着一个两难选择:他可以选择拒绝朋友而不分享,也可以选择破坏license而分享。两害相权取其轻,the lesser evil自然就是选择分享了(众笑)。(注:在演讲结束后有人问RMS对分享音乐怎么看,RMS说他坚决赞同应该分享,换来热烈鼓掌。还有人问到他对free chip design怎么看。RMS的回答是,现在一般人即使拿到一个chip design也无力生产芯片,但是如果到以后普通人可以自由复制和生产芯片的时候,他将会支持free hardware)除去道德方面的因素,软件自由还有着很多的益处。软件的自由带来了free market和democracy。Free market指的是,没有了垄断,任何business当需要定制什么软件时,就可以到市场上提出这个需求让程序员来做。Democracy指的是一个软件添加的特性由需求本身去推动,而不是由那些nasty companies来决定。最后,优秀的、最受欢迎的软件自然胜出。
接下来RMS回顾了GNU operating system的历史。GNU的名字是一个recursive name,这在当时是一个比较流行的幽默命名法,用XINY代表XINY Is Not Y。因为RMS想取代UNIX这个私有系统,但又同时兼容UNIX,所以就想取一个XINU代表XINU Is Not Unix。同时又要使得这个名字又是一个合法的英文单词,RMS便drop掉那个I,然后从anu、bnu、cnu开始查字典。查到gnu时,发现这个好(因为和new同音,这样gnu system就是new system可以制造很多笑话),于是GNU’s Not Unix便横空出世了。也许是为了和gnu区别,GNU的G是发音的(现在再称gnu system为new system可就不对啦,哈)。RMS发觉自己一个人写程序很辛苦,于是拉了一些人一起写,FSF也就产生了。为了取代UNIX,FSF开始一块一块的写程序将UNIX的组件取代,直到最后开始着手写kernel,也就是今天的Hurd。RMS将kernel设计成基于Mach的微内核,但没有自己写,而是聘请了别人写,好像是说写了6年都没写好。没有想到的是,Linus自己一年不到写了一个可用的monolithic kernel出来,并吸引了大家的注意力。相信Hurd后来半死不活也有部分原因是大家都去开发linux了。因为Linux系统用的userland程序都是来自GNU,RMS一直坚持称Linux为GNU/Linux。但是这也不能怪大家,gnu-slash-linux多难念啊。Microsoft Windows不也被简称为Windows么。
在为the Church of Emacs传教时,他还讲了几个关于VI的老笑话,例如”Using a free-software version of vi is not a sin; it is a penance.” 笑话中vi-vi-vi is the “editor of the beast” 引来的笑声最大。
I think the order in which the options are listed is along the same line as the real order of the passes.
For example, ghc -ddump-to-file -ddump-asm a.hs would dump the assembly to file a.dump-asm.
The option “-ddump-to-file” tells ghc to dump to a file, instead of to stdout. This feature does not seem to be documented.
GHC compiles Haskell source code down to native code, and then links in necessary Haskell libraries (written in Haskell) and RTS (written in C and C–). To see what libraries are linked in, pass -v to ghc.
Therefore, the lifetime of a Haskell program roughly looks like this:
The C Runtime (CRT) gets started first, which passes control to main. For C programs, main is defined by programmers; while for Haskell programs, main is defined by RTS in rts/Main.c. Next, RTS is initialized by calling startupHaskell in RtsStartup.c. Eventually, the computation that resides in mainIO_closure (a macro defined in Prelude.h that resolves to &ZCMain_main_closure) is kicked off from real_main. The closure data structure is defined as StgClosure/HaskellObj in includes/RtsAPI.h and includes/Closures.h.
In fact, because RTS is C code, you can play with its Makefile to produce a libHSrts.a with debugging information in it. Then you can link your Haskell program with this library to walk through the source of RTS in gdb.
The C libraries are not statically linked by default. To produce a completely static binary, run ghc -optl-static -optl-pthread a.hs. Any string following “-optl” is passed to gcc for the final linking step. Without “-optl-pthread”, you get errors like this:
wh5a@flitwick:/tmp$ ghc -optl-static a.hs
compilation IS NOT required
/usr/lib/gcc/i486-linux-gnu/4.2.3/../../../../lib/librt.a(timer_create.o): In function `timer_create’:
(.text+0×111): undefined reference to `pthread_once’
/usr/lib/gcc/i486-linux-gnu/4.2.3/../../../../lib/librt.a(timer_create.o): In function `timer_create’:
(.text+0×165): undefined reference to `pthread_attr_init’
/usr/lib/gcc/i486-linux-gnu/4.2.3/../../../../lib/librt.a(timer_create.o): In function `timer_create’:
(.text+0×1ab): undefined reference to `pthread_attr_setdetachstate’
/usr/lib/gcc/i486-linux-gnu/4.2.3/../../../../lib/librt.a(timer_routines.o): In function `__start_helper_thread’:
(.text+0×49): undefined reference to `pthread_attr_init’
/usr/lib/gcc/i486-linux-gnu/4.2.3/../../../../lib/librt.a(timer_routines.o): In function `__start_helper_thread’:
(.text+0×5c): undefined reference to `pthread_attr_setstacksize’
/usr/lib/gcc/i486-linux-gnu/4.2.3/../../../../lib/librt.a(timer_routines.o): In function `__start_helper_thread’:
(.text+0xab): undefined reference to `pthread_create’
/usr/lib/gcc/i486-linux-gnu/4.2.3/../../../../lib/librt.a(timer_routines.o): In function `__start_helper_thread’:
(.text+0xde): undefined reference to `pthread_attr_destroy’
/usr/lib/gcc/i486-linux-gnu/4.2.3/../../../../lib/librt.a(timer_routines.o): In function `__start_helper_thread’:
(.text+0xfa): undefined reference to `pthread_atfork’
/usr/lib/gcc/i486-linux-gnu/4.2.3/../../../../lib/librt.a(timer_routines.o): In function `timer_helper_thread’:
(.text+0×19d): undefined reference to `pthread_exit’
/usr/lib/gcc/i486-linux-gnu/4.2.3/../../../../lib/librt.a(timer_routines.o): In function `timer_helper_thread’:
(.text+0×1e5): undefined reference to `pthread_create’
/usr/lib/gcc/i486-linux-gnu/4.2.3/libgcc_eh.a(unwind-dw2.o): In function `uw_init_context_1′:
(.text+0×1904): undefined reference to `pthread_once’
collect2: ld returned 1 exit status
Looking at the above error, you may think passing “-optl-lpthread” instead of “-optl-pthread” would help, too. But as you can see in the verbose mode, “-lpthread” is passed to gcc too early. Another way to work around this error is to pass “-threaded” to ghc, which automatically adds “-lpthread” to the end of gcc’s command options because ghc knows you’re using the threaded Haskell library.
For more advanced tricks, refer to the script “kernel/ldhouse” from the House project.
This is a literate Haskell file, inspired by the paper
“Functional Programming with Overloading and Higher-Order Polymorphism” and Chapter 20 of TAPL.
In almost all programming languages, recursive types can be easily defined.
For example, a list of naturals can be defined as NatList = nil | cons Nat NatList.
This equation is not a simple definition, the right-hand side mentions the very name that we are defining.
This is just like how we ran into the difficulties of defining (anonymous) recursive functions!
Let us review how to define recursive functions first.
We can abstract this recursive equation as x = f x.
Suppose we have a magical fixed-point combinator, let’s call it Y, that for any f, Y f = f (Y f).
If such Y exists, Y f specifies the fixed point of the recursive equation x = f x.
It turns out such Y does exist for untyped lambda calculus : Y = \f.(\x.f(x x)) (\x.f(x x))
For recursive types, we make up a new combinator Mu, such that Mu f = f (Mu f).
Note that f here denotes a type constructor instead of a function.
NatList is the fixed-point of the equation X = nil | cons Nat X.
So it can be defined as NatList = Mu (\X. (nil | cons Nat X)). (”\” is overloaded here for abstraction at type level)
We do not explicitly define Mu because we cannot abstract over type constructors in Haskell.
If we could, the type system would be undecidable, *I think*.
Instead we’ll cheat and simply live with this definition: Mu f = f (Mu f).
Because Haskell requires a constructor for types, we have to define it in Haskell this way:
> newtype Mu f = In (f (Mu f))
This extra layer of In doesn’t change the mathematical property, because we can view In as an isomorphism.
And here’s the reverse isomorphism:
> out :: Mu f -> f (Mu f)
> out (In x) = x
Let’s see how Nat plays out. We first define the equation, and then pass the equation to Mu:
> data NatF b = Zero | Succ b
> type Nat = Mu NatF
The elements in Nat are: In Zero, In $ Succ (In Zero), In $ Succ (In $ Succ (In Zero)), …
This extra layer of indirection helps formalize recursive types. But does it have any practical applications?
The first application was illustrated in the paper “Functional Programming with Bananas, Lenses, Envelopes and Barbed Wire”
In fact, rumor has it that there was a PhD who ate so many bananas that his eyes bugged out, now he needs new lenses!
(”The Evolution of a Haskell Programmer”)
We note that NatF happens to be a functor:
> instance Functor NatF where
> fmap f Zero = Zero
> fmap f (Succ x) = Succ (f x)
Fold on lists generalizes the pattern of performing some repetitive operations on a homogeneous structure.
Why not generalize fold to any recursively defined structure?
As it turns out, we have catamorphism and anamorphism.
> cata :: Functor f => (f a -> a) -> Mu f -> a
> cata phi = phi . fmap (cata phi) . out
> ana :: Functor f => (a -> f a) -> a -> Mu f
> ana psi = In . fmap (ana psi) . psi
With bananas (cata) and lenses (ana) we can start defining many REALLY higher-order functions:
> zero :: Nat
> zero = In Zero
> elim z s Zero = z
> elim z s (Succ n) = s n
> intro z s 0 = z
> intro z s n = s (n-1)
> instance Enum Nat where
> succ = In . Succ
> toEnum = ana (intro Zero Succ)
> fromEnum = cata (elim 0 (1+))
> instance Show Nat where
> show = cata (elim “Zero” (”Succ “++))
> instance Eq Nat where
> x == y = (fromEnum x) == (fromEnum y)
> instance Num Nat where
> (+) m = cata (elim m succ)
> (*) m = cata (elim zero (m+))
> fromInteger = ana (intro Zero Succ)
Let’s see another example: polymorphic lists.
> data L a b = Nil | Cons a b
> type List a = Mu (L a)
> instance Functor (L a) where
> fmap f = lelim Nil (\a b -> Cons a (f b))
> lelim n c Nil = n
> lelim n c (Cons a b) = c a b
> toList = cata (lelim [] (:))
> instance Show a => Show (List a) where
> show = show . toList
try out:
In Nil, In $ Cons 3 $ In $ Cons 2 $ In Nil
Another benefit is one way to address the so called Expression Problem raised by Philip Wadler:
The Expression Problem is a new name for an old problem. The goal is
to define a datatype by cases, where one can add new cases to the
datatype and new functions over the datatype, without recompiling
existing code, and while retaining static type safety (e.g., no
casts). For the concrete example, we take expressions as the data
type, begin with one case (constants) and one function (evaluators),
then add one more construct (plus) and one more function (conversion
to a string).
Whether a language can solve the Expression Problem is a salient
indicator of its capacity for expression. One can think of cases as
rows and functions as columns in a table. In a functional language,
the rows are fixed (cases in a datatype declaration) but it is easy to
add new columns (functions). In an object-oriented language, the
columns are fixed (methods in a class declaration) but it is easy to
add new rows (subclasses). We want to make it easy to add either rows
or columns.
By pushing the indirect way of defining types further, Wouter Swierstra in his paper “Data types (a la carte)” talks about an approach to decoupling rows (cases in a datatype declaration).
In the paper, every cases get their own data type declaration (rather than being packed together as an union type), and then are injected into a coproduct that acts as the final type.
I recently came across a monad transformer tutorial by Martin Grabmüller and found it quite enjoyable.
I felt it may be even more helpful to add some discussion on the design of the monad transformer library.
So I added two subsections (Section 2.2 and 2.5) based on my understanding.
As I myself is still learning Haskell, there could well be many errors.
The literate haskell file can be proprocessed by lhs2Tex and then used to generate a PDF.
The typesetting in the PDF file is screwed at some places for some reason I don’t know, but that’s OK.
PS: If you want to see the code of Monad Transformer Library, note that it’s in ghc’s extralibs, not corelibs.
If you’re running debian, apt-get source libghc6-mtl-dev.
Do not trust the kernel build tools on macosforge if you want to build Leopard.
Their tools are outdated (as of today) and will give you tons of errors when compiling.
So, better to compile the tools (kext_tools and cctools) from source.
The “Mac OS X Internals” book gives detailed information in Section 6.10.
To fine tune the compile settings, refer to the README file in the xnu package.
After successfully compiling xnu, you need to copy your kernel to the root directory and fix the permissions:
Now, on reboot simply tell the boot loader to load your kernel instead of the default mach_kernel:
> my_kernel
PS: There are some annoying complaints about missing of ctfconvert.
ctfconvert is supposed to come with dtrace, but when I tried to build dtrace from source I got errors about missing header files from libiberty. I didn’t investigate further beyond that. THe missing of ctfconvert seems irrelevant here.
Apple has hidden a poem inside OS X that warns users not to pirate the operating system.
There once was was a user that whined
his existing OS was so blind,
he’d do better to pirate
an OS that ran great
but found his hardware declined.
Please don’t steal Mac OS!
Really, that’s way uncool.
What’s the deal?
Basically, Apple wants to make it hard to run its Intel-based OS X on PCs, by AES-encrypting some key applications like Finder, Dock, and Rosetta (ha, sounds like instruction-set randomization again!). Of course, there must be something behind the scene to restore (read: decrypt) the scrambled binaries. Apple uses a kernel extension dsmos (/System/Library/Extensions/Dont Steal Mac OS X.kext) to do this job. For now this decryption is all done in software, and I suppose the binaries are statically encrypted with fixed keys. So this extra protection doesn’t help much with defeating piracy. In the future though, I’d expect Apple to make use of TPM to authenticate the hardware and do the decryption.
The major obstacle of OS X86 (aka Hackintosh), is that legacy PCs only come with BIOS, but OS X only runs on EFI. Hackers had to either patch the kernel to remove its dependence on EFI, or patch the bootloader to emulate EFI so that the vanilla kernel can run. Ironically, Apple had the same problem the other way around: it upgraded its EFI to include BIOS support so that Windows XP can run. Besides the EFI hack, SSE3 instructions in the kernel have to be patched or emulated on old CPUs.
Recently, there have been a lot of discussions around how WP stores authentication cookies.
It is nice that the developers are addressing this design flaw.
The change was made on Dec 17 (revision 6387).
However, this change made my blog management pages fail to show up, rendering my blog completely unusable.
I don’t know what happened, but I temporarily worked around this issue by rolling back the revision to an earlier date.
The command for that is: svn up -r {2007-12-16}
PS: A little bit about how I ran into this problem and found the cause.
Although I was aware of the cookie bug of WP, I didn’t know the developers had already started to fix it.
I simply do a svn up every few days when I feel like it.
So, today I did a routine update and found my blog unusable.
Then, I tried every date before today and nailed down the problem in the 12-17 version.
The next thing I did was to examine the change logs and the diffs: svn diff -r {2007-12-16}:{2007-12-17}
svn log -r {2007-12-16}:{2007-12-17}
Judging from the change logs, my immediate gut feeling was that there must be something wrong with the “new secure cookie protocol”.
Recent Comments