# Portability Portable Operating Systems * Assembly is kept to a minimum * and interfaces and features are sufficiently general and abstract so that they work on a wide range of architectures * optimal code is traded for portable code Linux * much fast-path and low-level code is architecture-dependent and often written in assembly * This approach enables Linux to remain portable without foregoing optimizations example ![](https://i.imgur.com/Lgl1ZoZ.png) ![](https://i.imgur.com/LZxuljp.png) ![](https://i.imgur.com/d2UXMEP.png) # History of Portability in Linux ![](https://i.imgur.com/wK5lrzU.png) ![](https://i.imgur.com/BOClfL3.png) # Word Size and Data Types 一個word是machine一個單位時間能執行的data量 當你說一個machine是"n-bits"的時候,通常就在講這個machine's word size. * 32bits * 4bytes (word size) * 64bits * 8bytes (word size) > The size of a processor’s general-purpose registers (GPRs) is equal to its word size > > The widths of the components in a given architecture—for example, the memory bus—are usually at least as wide as the word size > > Typically, at least in the architectures that Linux supports, the virtual memory address space is equal to the word size > * the size of a pointer is equal to the word size * the size of the C type long is equal to the word size * whereas the size of the int type is sometimes less than that of the word size ![](https://i.imgur.com/vO3N4L3.png) ![](https://i.imgur.com/0teKvSN.png) ![](https://i.imgur.com/xbjEIQa.png) ![](https://i.imgur.com/U86IOXC.png) # Opaque Types (不透明的types) * pid_t * atomic_t * dev_t * gid_t * uid_t ![](https://i.imgur.com/6VOb5fd.png) # Special Types ![](https://i.imgur.com/K3bbx16.png) ![](https://i.imgur.com/LYKLVWX.png) # Explicitly Sized Types ![](https://i.imgur.com/A3qinAv.png) ![](https://i.imgur.com/CqlfmQZ.png) ![](https://i.imgur.com/hEzdUgh.png) ![](https://i.imgur.com/M9o9SEc.png) ![](https://i.imgur.com/VxQCKl4.png) # Signedness of Chars 不要心中有預設char是 signed or unsigned 不同架構default不一樣 ARM: unsigned ![](https://i.imgur.com/TQggyhM.png) # Data Alignment 定義 ![](https://i.imgur.com/IRCMR3s.png) 有些architectures有比較嚴格的定義,在有些RISC based的機器上,loading一個unaligned data可能會導致processor trap(a handled error). 不然也會導致performance degradation. # Avoiding Alignment Issues The compiler generally prevents alignment issues by naturally aligning all data types 所以所有的變數型態default都是alignment的 * Accessing an aligned address with a recast pointer of a larger-aligned address causes an alignment issue ![](https://i.imgur.com/Zy8jsvT.png) 這個例子把 pointer to char casting成一個 unsigned long. 會導致32 or 64bits unsigned long變數被loading進來cpu,但不是4 or 8的倍數 # Alignment of Nonstandard Types ![](https://i.imgur.com/3htjppZ.png) # Structure Padding ![](https://i.imgur.com/K9q4u6t.png) ![](https://i.imgur.com/3poWUpE.png) ![](https://i.imgur.com/laXLJBO.png) ![](https://i.imgur.com/OfwN9fi.png) ![](https://i.imgur.com/RaCBXKQ.png) ANSI C有規定compiler永遠不能改變structure members的先後順序.所以妳自己要決定順序。 實際上也不能改,一改就會崩潰,因為在計算function裡面的variables的位置都是用base address + offsets去算的 ![](https://i.imgur.com/1ijYkCS.png) gcc -Wpadded可以警告你那些structure有被加上padding # Byte Order Byte ordering is the order of bytes within a word * Big-endian * little-endian ![](https://i.imgur.com/lFbZZCu.png) ![](https://i.imgur.com/9KdrkhW.png) * X86: little-endian * others: big-endian Consider the number 1027 ![](https://i.imgur.com/W5JYm8U.png) ![](https://i.imgur.com/JYvzIRS.png) 測試系統是哪種endian ![](https://i.imgur.com/fFSjxlk.png) architecture in linux要define兩者其中之一 in <asm/byteorder.h> * __BIG_ENDIAN * __LITTLE_ENDIAN 還可以互相轉換 ![](https://i.imgur.com/yZoJTzn.png) # Time The measurement of time is another kernel concept that can differ between architectures or even kernel revisions. 不要亂猜,這些kernel版本不同都有可能不同 * the frequency of the timer interrupt * number of jiffies per second always use HZ to scale your units of time correctly For example * 2.6之後x86 : HZ is 100 * the timer interrupt occurs 100 times per second * or every 10 milliseconds * 2.6之前x86 : HZ is 1000 * Alpha: HZ is 1024 * ARM: HZ is 100 ![](https://i.imgur.com/aNCZubj.png) # Page Size 永遠不要亂猜page size是多少 x86-32的programmers常常會亂猜page size = 4KB x86上的確是這樣,但其他architectures有不同大小,很多architectures支援 multiple page sizes! ![](https://i.imgur.com/Bavm0ow.png) 所以請用macro * PAGE_SIZE = the size of a page in bytes * PAGE_SHIFT = number of bits to left-shift an address to derive its page number. EX: on X86-32 with 4KB pages * PAGE_SIZE is 4096 * PAGE_SHIFT is 12 # Processor Ordering 善用 barrier ![](https://i.imgur.com/sZMYspV.png) ![](https://i.imgur.com/JciVVdf.png) # SMP, Kernel Preemption, and High Memory 永遠預設這三種情況下去coding ![](https://i.imgur.com/otlLicB.png) Conclusion ![](https://i.imgur.com/wu8RqsJ.png) 要寫portable code需要注意這些 * wordsize * data type size * alignment * padding * byte order * signedness * endianness * page size * processor load/sotre ordering * 永遠要注意你用的data types是不是最正確的