Chủ Nhật, 28 tháng 4, 2013

syntax errors and exceptions

Trước nhất chúng ta cần phân biệt hai khái niệm lỗi cú pháp (syntax errors) và ngoại lệ (exception)

1. Syntax errors
Syntax errors được biết đến như parsing errors (lỗi phân tích cú pháp ), đây là một lỗi thường gặp khi ta bắt đầu học Python:

>>> while True print('Hello world')
  File "<stdin>", line 1, in ?
    while True print('Hello world')
                   ^
SyntaxError: invalid syntax

parser (bộ phân tích ) lập lại dòng gây lỗi, và có một mũi tên nhỏ chỉ đến phần đầu tiên gây ra lỗi. Lỗi được tạo ra bởi dấu hiệu đằng trước mũi tên: Trong ví dụ này: lỗi được tìm thấy tại print function, lí do là vì (':') bị missing trước đó. File name, và line number được in ra vì vậy bạn biết được input được lấy từ đâu. 

2. Exceptions
Ngay cả khi một statement hay là expression là đúng về mặt cú pháp, nó có thể tạo ra lỗi khi một cố gắng được tạo ra để thực thi nó. Errors được tìm thấy trong suốt quá trình thực thi được gọi là exceptions và nó không là unconditionall fatal. tuy nhiên, hầu hết exception không được handled bởi programs , và kết quả trong error messages 

>>> 10 * (1/0)
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
ZeroDivisionError: int division or modulo by zero
>>> 4 + spam*3
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
NameError: name 'spam' is not defined
>>> '2' + 2
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
TypeError: Can't convert 'int' object to str implicitly

Dòng cuối của error message ám chỉ điều gì đã xảy ra. Các exceptions xuất hiện theo các kiểu khác nhau và kiểu được in như một phần của message, các kiểu trong ví dụ là : Zero Devision Error , NameError, TypeError. string được in như là exception type là tên của built-in exception đã xuất hiện. Đó là đúng cho tất cả built-in exceptions, nhưng nó không cần là đúng cho user-defined exceptions (mặc dù đó là convention hữu dụng). các tên ngoại lệ chuẩn là các built-in identifiers.

Phần còn lại của dòng cung cấp thông tin chi tiết dựa trên kiểu của ngoại lệ và những gì tạo ra nó. 

Phần đằng trước của error message chỉ ra ngữ cảnh nơi ngoại lệ xảy ra, trong một form của traceback stack. Nói chung nó chứa một traceback stack liệt kê source lines, tuy nhiên nó sẽ không display dòng đọc từ chuẩn input. 

3. Handling exception
Chúng ta có thể viết programs để handle selected exceptions. Nhìn vào ví dụ sau đây, những gì yêu cầu user nhập dữ liệu cho đến khi dữ liệu đó là một số nguyên hợp lệ, nhưng cho phép user interupt program  (sử dụng control-C hay bất cứ OS support), chú ý rằng interupt do user sinh ra được báo hiệu bởi việc raising KeyboardInterupt exception 

>>> while True:
...     try:
...         x = int(input("Please enter a number: "))
...         break
...     except ValueError:
...         print("Oops!  That was no valid number.  Try again...")
...

try statement làm việc như sau:
  • Thứ nhất, try clause  (statement(s) giữa try except  keywords ) được thực thi. 
  • Nếu không có exception xảy ra, except clause  đươc bỏ qua và thực thi try statement được hoàn thành. 
  • Nếu exception xảy ra trong suốt quá trình thực thi cảu try clause, phần còn lại của clause được bỏ qua. Sau đó nều kiểu của nó matches exception named sau except keyword, except clause được thực thi và sau đó excution sẽ tiếp tục sau try statement.
  • Nếu một exception xảy ra không match với exception named in except clause, nó được chuyển đến phía ngoài của try  statements, nếu không có handler được tìm thấy, nó là một unhandled exception  và excution stops với message được chỉ ra phía trên. 
try statement có thê có nhiều hơn một except clause  , để chỉ ra handlers cho các exceptions khác nhau. Tối đa một handler sẽ được thực thi. handlers chỉ handle exceptions mà xảy ra tương ứng với try clause. except clause có thể name nhiều exceptions trong một tuple, cho ví dụ :
... except (RuntimeError, TypeError, NameError):
...     pass


Thứ Bảy, 27 tháng 4, 2013

Kernel mode vs. User mode

Để bảo vệ user apps tránh khỏi việc accessing và modifying các dữ liệu quan trọng của OS, Windows sử dụng 2 processor access modes (thậm chỉ process processor, những gì Windows đang running supports nhiều hơn 2 ) : user mode kernel mode. User application code runs trong usermode, trái lại OS code (như là system services và device drivers ) runs trong kernel mode. kernel mode refers đến mode của thực thi trong processor, được cấp quyền truy nhập đến tất cả system memory và tất cả CPU instructions. Bởi việc cung cấp OS software với đặc quyền cao hơn application software có, processor cung cấp nền tảng cho OS designers để đảm bảo các misbehaving application không thể làm gián đoạn sự ổn định của hệ thống.

Note: cấu trúc của Inter x86 processor định nghĩa 4 mức độ đặc quyền, hoặc rings, để bảo vệ system code và dữ liệu tránh khỏi việc ghi đè bởi việc vô tình hay cố tình bởi code có quyền thấp hơn. Windows sử dụng mức độ đặc quyền 0 (or ring 0) cho kernel mode và mức 3 cho user mode. Lí do Windows chỉ sử dụng 2 mức độ là do một vài kiến trúc phần cứng được supported trong quá khứ (như là Compaq Alpha và Silicon Graphics MIPS ) implemented chỉ hai mức độ đặc quyền.

Mặc dù mỗi Windows process có không gian bộ nhớ riêng của nó, kernel-mode OS và và device driver chia sẻ single virtual address space. Mỗi page trong virtual memory được đánh dấu như là để những thể hiện là những access mode gì processor phải đọc hay viết page.

Page trong không gian system chỉ có thể được accessed từ kernel mode, tái lại tất cả cac pages trong không gian địa chỉ user có thể được truy nhập từ user mode. Read-only pages (như là các pages chứa excutable code) không thể được viết từ bất kì mode nào cả.

Windows không cung cấp bất cứ sự bảo vệ nào đến private read/write system memory được sử dụng bởi các thành phần trong kernel mode. Hay nói cách khác, mỗi khi trong kernel, OS và device driver code có truy nhập hoàn toàn đến system space memory và có thể bypass Windows security để access objects. Bởi vì một số lượng lớn Windows OS code run trong kernel mode, điều quan trọng là các thành phần run trong kernel mode được thiết kế cẩn thận và được kiểm tra cẩn thận để không gây ảnh hưởng đến system security.

Sự thiếu hụt còn nhấn mạnh nhu cầu cần được quan tâm khi loading third-party device driver, bởi vì mỗi khi có mặt trong kernel mode software có thể truy nhập một cách hoàn toàn đến tất cả OS data. vulnerability này là một trong những lí do đằng sau cơ chế driver-signing được giới thiệu trong Windows, những gì cảnh báo user nếu một nỗ lực được tạo ra để thêm một unauthorized (unsigned) driver. Ngoài ra, một cơ chế được gọi là Driver Verifier giúp người viết device driver tìm được bugs (như là buffer overruns hoặc memory leaks).

Như bạn đã biết, user apps chuyển từ user mode đến kernel mode khi chúng tạo ra system service call. Cho ví dụ, Windows ReadFile thậm chí cần gọi internal windows routine  để thực sự handles read data từ file. routine đó, bởi vì nó access đến các cấu trúc dữ liệu bên trong hệ thống, phải được run trong kernel mode. việc chuyển từ user mode sang kernel mode được hoàn thành bởi việc sử dụng một special processor instruction, làm cho processor switch đến kernel mode. OS traps instruction đó, chú ý răng một system service được requested, hợp lệ hóa các arguments thread passed đến system function, và sau đó thực thi internal function. Trước khi trả lại điều khiển cho user thread, processor mode được switched trở lại user mode. Theo cách này OS bảo vệ được dữ liệu của chính nó từ việc quan sát chăm chú và sự chỉnh sửa từ phía user processes.

Điều bình thường đó là user thread spend một phần thời gian của nó trong user mode, và một phần trong kernel mode. Sự thực là , bởi vì một lượng lớn graphic và windowing system được run trong kernel mode, các ứng dụng chuyên đồ họa cần nhiều thời gian trong kernel mode hơn là trong user mode. Một cách dễ dàng để kiểm tra đó là run các graphics-intensive application như là MS paint hoặc MS pinball và quan sát thời gian split giữa user mode và kernel mode sử dụng một trong các biến đếm

Virtual Memory in Windows

Windows implements một hệ thống bộ nhớ ảo (virtual memory system ) dựa trên không gian địa chỉ phẳng (flat) hay còn gọi là không gian địa chỉ tuyến tính (linear), cung cấp cho mỗi process với ảo tưởng rằng có một không gian địa chỉ lớn và riêng tư (private) danh cho mỗi process. VM (virtual memory) cung cấp một tầm nhìn luận lý của bộ nhớ và có thể không tương ứng với bố trí vật lý của nó. Tại run time, memory manager, với sự trợ giúp từ hardware, translates hoặc maps, địa chỉ ảo vào trong địa chỉ vật lý, nơi dữ liệu thực sự được lưu. Bằng việc điểu khiển sự bảo vệ và mapping, OS có thể đảm bảo rằng mỗi individial processes không đụng vào bên trong processes khác cũng như là overwrite OS data.

Bởi vì hầu hết hệ thống có ít physical memory (PM) hơn so với tổng VM trong sử dụng bởi việc running processes, memory manager transfers, hoặc pages, một vài memory contents lên đĩa. Paging data lên đĩa giải phóng PM vì vây nó có thể được sử dụng cho processes khác hoặc là cho chính OS. khi một thread access đến một VA (virtual address) đã được paged lên đĩa, virtual memory manager loads thông tin quay trở lại memory từ đĩa. Apps không cần phải thay đổi để theo bất cứ cách nào để "take advantage" về paging bởi vì hardware support enables memory manager để page mà không có "knowledge" hay sự trợ giúp của processes hoặc threads.

Kích thước không gian bộ nhớ ảo khác nhau đối với mỗi nền tảng hardware. Trên 32bit x86 system, tổng không gian địa chỉ ảo theo lý thuyết tối đa lên tới 4GB. Mặc định, Windows cấp phát một nửa trong số đó (một nửa dưới của 4GB virtual address space, từ x00000000 tới x7FFFFFFF) đến processes làm thành nơi lưu trữ cá nhân đơn nhất (unique private storage) và sử dụng nửa phần còn lại (nửa trên, từ x80000000 đến xFFFFFFFF) cho việc tận dụng bộ OS memory được bảo vệ của riêng nó. Việc mapping phần dưới thay đổi để thể hiện không gian địa chỉ ảo của process đang chạy hiện thời, nhưng việc mapping phần trên bao gồm cả bộ nhớ ảo của cả hệ điều hành. Windows 2000 Advanced Server, Windows 2000 Data Center, Windows XP (SP2 trở về sau) và Windows Server 2003 support boot-time options (/3GB và /USERVA qualifiers trong Boot.ini ) gửi đến cho processes running specially marked programs (không gian địa chỉ lớn biết flag được set trong header của excutable image) khả năng sử dụng lên tới 3GB của private address space (1GB cho OS). option này cho phép các apps như là database servers có thể giữ lượng lớn portions của DB trong không gian địa chỉ process, do đó giảm đi nhu cầu map subset views của database.

Mặc dù 3GB là lớn hơn 2GB, nhưng nó vẫn là không đủ virtual address space để map một lượng lớn DB có thê lơn tới nhiều GB. Để giải quyết việc này, Windows cung cấp một cơ chế được gọi là Address Windowing Extension (AWE) , những gì cho phép 32 bit app cấp phát lên đến 64GB của PM và sau đó map views, hoặc windows, vào trong 2-GB không gian địa chỉ ảo của nó. Mặc dù sử dụng AWE đặt gánh nặng việc quản lí mappings PM lên programers, nó giải quyết nhu cầu truy nhập trực tiếp nhiều hơn physical memory hơn là có thể được mapped mỗi lần  trong 32 bit process address space.

64 bit Windows cung cấp không gian địa chỉ lớn hơn cho processes: 7152 GB trên Itanium system và 8192 GB trên x64 system.

Thứ Sáu, 26 tháng 4, 2013

Character Sequences

Như đã biết, Thư viện chuẩn C++ implements một lớp string , những gì hữu dụng cho ta khi handle và thao tác chuỗi các kí tự. Tuy nhiên bởi vì strings thực chất là thứ tự của các kí tự, chúng ta có thể biểu diễn chúng như một mảng với thành phần là các kí tự.

Cho ví dụ mảng sau:

 
char jenny [20];

la một mảng có thể lưu trữ đến 20 kí tự kiểu char. Nó có thể được biểu diến bằng 20 ô vuông liền kề nhau, mỗi ô vuông đại diện cho một kí tự. 

Theo đó, trong mảng này, chúng ta có thể lưu sequences of charcters với độ dài lên tới 20 kí tự. nhưng chúng ta cũng có thể lưu sequences ngắn hơn. Ví dụ jenny có thể lưu một vài điểm trong chương trình hoặc là sequence "hello" hoặc là sequence "Merry Christmas", cả hai đều có độ dài ngắn hơn 20 kí tự. 

Do đó, mảng của các kí tự có thể lưu các sequence ngắn hơn so với tổng độ dài của nó, một kí tự đặc biệt đươc sử dụng để báo hiệu kết thúc sequence hợp lệ: the null character, những gì sở hữu literal constant đươc viết như là '\0' (backslash, zero).

Mảng của chúng ta có 20 phần tử kiểu char, được gọi là jenny , khi lưu trữ "hello world" và "Merry christmas" thì có thể được biểu diễn như sau:


Chú ý rằng cách null character được thêm vào sau nội dung hợp lệ để ám chỉ kết thúc sequence. Các panels màu nâu là các char elements với các giá trị chưa được xác định. 

Initialization of null-terminated character sequences

Bởi vì mảng của các kí tự là các mảng thông thường nên chúng tuân theo các luật của mảng. Cho ví dụ, nếu bạn muốn khởi động một mảng các kí tự với một thứ tự các kí tự đã được định nghĩa trước, bạn có thể làm việc này như bất cứ mảng nào khác:


char myword[] = { 'H', 'e', 'l', 'l', 'o', '\0' };

Trong trường hợp này chúng ta khai báo một mảng có 6 phần tử kiểu kí tự, khởi tạo với các kí tự trong "hello" và thêm null character "\0" vào cuối. 

Nhưng mảng các kí tự có thêm những phương thức để khởi tạo giá trị của họ: sử dụng string literals. 
String literals cho ví dụ :


"the result is: "

String literals được bao bởi "" thường xuyên có null character ('\0') tự động nối sau đuôi. 

Do đó chúng ta có thể khởi tạo mảng các kí tự được gọi là myword với null character bằng một trong hai phương thức sau:

char myword [] = { 'H', 'e', 'l', 'l', 'o', '\0' };
char myword [] = "Hello"; 
Trong cả hai trường hợp mảng của các kí tự myword  được khai báo với kích thước là 6 phần tử, 5 kí tự được soạn cho "hello" và thêm vào kí tự cuối cùng là '\0' những gì chỉ ra là tận cùng của sequence. Trong trường hợp thứ 2, khi sử dụng "" thì null character tự động được nối vào. 
Chý ý rằng chúng ta đang nói về khởi tạo một mảng các kí tự, như là nó được khai báo, chứ ta không nói về việc gán giá trị đến chúng mỗi khi chúng được khai báo. Sự thực, bởi vì kiểu mảng kết thúc bởi null character là các mảng thông thường chúng ta có một vài giới hạn như đối với các mảng khác, vì vậy chúng ta không thể copy blocks of data với phép gán. 
Giả sử mytest  là một char[] variable, một expression trong source code giống như:
mystext = "Hello";
mystext[] = "Hello";

là không hợp lệ, muốn hợp lệ nó phải như sau 

 
mystext = { 'H', 'e', 'l', 'l', 'o', '\0' };
Nguyên nhân có thể được giải thích nếu bạn có hiểu biết về con trỏ, bởi vì sau đó nó sẽ được làm rõ rằng thực chất một mảng là một constant pointer trỏ đến môt block of memory. 

Using null-terminated sequences of characters

Null-terminated sequences of characters là một cách tự nhiên để "treating" strings trong C++ , vì vật chúng có thể được sử dụng trong nhiều thủ tục. Thực tế, regular string literals có kiểu đó (char []) và còn được sử dụng trong nhiều trường hợp. 

Cho ví dụ cin cout support null-terminated sequences như là containers hợp lệ cho sequences of characters, vì vậy bạn có thể sử dụng chúng trực tiếp để extract strings của các kí tự từ cin hoặc chèn thêm chúng vào trong cout. cho ví dụ:

// null-terminated sequences of characters
#include <iostream>
using namespace std;

int main ()
{
  char question[] = "Please, enter your first name: ";
  char greeting[] = "Hello, ";
  char yourname [80];
  cout << question;
  cin >> yourname;
  cout << greeting << yourname << "!";
  return 0;
}
Please, enter your first name: John
Hello, John!
Như chúng ta có thể thấy, chúng ta khai báo 3 mảng kí tự. Hai mảng đầu được khởi tạo với string literals constant, trong khi mảng thứ 3 thì chưa định nghĩ, đơn thuần chỉ là khai báo một mảng có 80 kí tự. Kích thước của 2  mảng đầu được xác định là độ dài của literal constant chúng khởi tạo. 

Cuối cùng, sequences of characters được lưu trong mảng char có thể dễ dàng chuyển đổi sang string objects bởi việc sử dụng phép gán.

string mystring;
char myntcs[]="some text";
mystring = myntcs;

Thread

Thread là một thực thể nằm bên trong một process mà Windows lập lịch cho thực thi. Nếu không có nó, process'program không thể run. Một thread bao gồm những thành phần cơ bản sau:
  • Nội dung của tập các CPU registers biểu diễn trạng thái của processor.
  • 2 stacks, một được sử dụng cho thread khi thực thi trong kernel mode, cái còn lại trong user mode.
  • một khu lưu trữ cá nhân (private) được gọi là thread-local storage (TLS) phục vụ nhu cầu của subsystems, run-time libraries và các DLLs.
  • một số định danh duy nhất được gọi là thread ID 
  • threads thỉnh thoảng có những security context của riêng chúng và thường được sử dụng bởi multithreaded server application.
Những registers, stacks, và private storage area còn được gọi là thread's context. Bởi vì thông tin này là khác nhau đối với từng kiến trúc máy tính mà Windows chạy trên đó. Windows GetThreadContext function cung cấp khả năng truy nhập đến thông tin về kiến trúc (được gọi là CONTEXT block )

Mặc dù mọi threads đều có ngữ cảnh thực thi riêng của nó, mọi thread bên trong một process chia sẻ chung không gian địa chỉ ảo của process (thêm vào đó là phần còn lại của resources thuộc về process), nghĩa là tất cả các threads trong process có thể viết và đọc từ bộ nhớ lẫn nhau.
Tuy nhiên threads không thể đột ngột tham chiếu đến không gian địa chỉ của process khác nếu process khác không tạo ra "available part" của không gian địa chỉ private của nó như là shared memory section (còn được gọi là file mapping object ) hoặc process khác không mở một process khác để sử dụng cross-process memory functions như là ReadProcessMemory WriteProcessMemory.

Ngoài private address space và một hay nhiều threads, mỗi process có một security identification  và một list của open handles đến các đối tượng như files, shared memory sections hoặc một trong những đối tượng đồng bộ như mutexes, events, hoặc semaphores

Mỗi process có security context được lưu trong một object được gọi là access token. process access token chứa security identification và thông tin quan trọng cho process. Mặc định, threads không có access token của riêng chúng. nhưng chúng có thể đạt được một cái, do vật cho phép individual threads giả mạo security context của process khác- bao gồm cả processes chạy trên remote Windows system- mà không ảnh hưởng đến threads khác trong process.

virtual address descriptors (VADs) là các cấu trúc dữ liệu mà memory manager sử dụng để "keep track" các virtual addresses mà process đang sử dụng.

Windows cung cấp một mở rộng đến process model được gọi là job. job's object main function là để cho phép các nhóm processes được quản lí và thao tác như là một đơn vị. job object cho phép điều khiển các thái độ và cung cấp giới hạn cho process hoặc process liên kết vơi job. Nó còn records các thông tin cơ bản cho tất cả processes liên kết với job nhưng từ khi kết thúc. Theo một vài cách, job object bù vào phần thiếu hụt của cấu trúc cây process trong Windows- cho đến giờ theo nhiều cách nó cần mạnh mẽ hơn so với Unix-style process tree. 

Thứ Sáu, 12 tháng 4, 2013

Memory management

Bộ nhớ là một resource quan trọng cần được quản lý một cách cẩn thận.
Một phần việc của OS là quản lý memory hierachy được gọi là memory manager. Công việc của nó là keep track những phần nào của memory là đang sử dụng và nhưng phần nào là không in use, để cấp phát bộ nhớ đến processes khi họ cần nó, và giải phóng khi các processes hoàn thành, và để quản lý swapping giữa bộ nhớ chính và disk khi main memory quá nhỏ để giữ tất cả processes.

BASIC MEMORY MANAGEMENT
Các hệ thống quản lý bộ nhớ có thể chia ra thành 2 classes. Nhưng cái move processes ra và vào giữa disk và main memory trong suốt thực thi và những cái không thực hiện điều này. Chúng ta hãy luôn keep in mind rằng swapping và paging tạo bởi sự thiếu hiệu quả khi main memory giữ tất cả program at once.

Như ta đã biết software thường phát triển nhanh hơn memory, vì vậy một cơ chế hiệu quả để quản lý bộ nhớ là cần thiết.

Monoprogramming without Swapping or Paging
cơ chế quản lý bộ nhớ đơn giản nhất là chỉ chạy một program tại một thời điểm, sharing memory giữa OS và program. Cơ 3 kiểu khác nhau trong cơ chế này đó là : OS có thể nằm tại đấy memory trong RAM hoặc nó có thể nằm trong ROM tại đỉnh của bộ nhớ. hoặc là device drivers có thể nằm tại đỉnh của memory trong ROM, OS nằm trong RAM. Cách thứ nhất thường được dùng trong mainframes và minicomputers nhưng ngày nay hiếm được dùng. mô hình thứ 2 được sử dụng bởi palmtop computers và các hệ thống nhúng. mô hình thứ 3 được sử dụng bởi các máy tính cá nhân thế hệ đầu (ví dụ running MS-DOS), nơi mà một phần trong ROM được gọi là BIOS (BASIC INPUT OUTPUT SYSTEM).

Khi hệ thống được tổ chức theo cách này, chỉ một process được running tại một thời điểm. Miễn là user types một command, OS copy program được yêu cầu từ disk vào memory và executes nó. khi process finishes, OS display một prompt character và chờ cho một new command. Khi nó nhận được command, nó loads new program vào trong memory, overwriting cái đầu tiên.

Multiprogramming with Fixed Partitions
Ngoại trừ ra các hệ thống nhúng đơn giản, monoprogramming là khó được sử dụng. Hầu hết modern OS cho phép multiple processes run tại cùng một thời điểm. Có multiple processes running có nghĩa là khi một process bị blocked chờ cho I/O finish, một process khác có thể sử dụng CPU. Do đó multiprogramming tăng CPU utilization. Network servers thường xuyên có khả năng run nhiều processes (cho các clients khác nhau) tại cùng một thời điểm, hầu hết client (ví dụ desktop ) đều có khả năng này.

Cách đơn giản nhất để đạt được multiprogramming đó là chia memory thành n partitions.
khi một job đến, nó có thể được đạt trong input queue của partition nhỏ nhất và đủ lớn để giữ nó. Bởi vì partition đước fixed trong cơ chế này, bất cứ space trong partition không được sử dụng bởi job sẽ bị mất.

Sự bất lợi trong việc sắp xếp các incoming jobs vào trong các queue tách biệt nhau là rõ ràng khi một queue cho một partition lớn là empty còn queue cho partition nhỏ thì lại full. Hậu quả có thể xảy ra là các small jobs có thể phải đợi để có được bộ nhớ trong khi còn rất nhiều memory available. Một cách tổ chức thay thế đó là duy trì single queue . Bất cứ khi nào một partition trở nên free, job gần nhất với đầu của queue có thể được fit vào trong partition thì có thể được load vào và run. Một điều không mong muốn là lãng phí một partition lớn với một small job, một chiến lược khác là tìm trong toàn bộ input queue, bất cứ khi nào partition trở nên free và pick largest job có thể fits.

Thứ Năm, 11 tháng 4, 2013

Link layer

Như đã biết, lớp mạng cung cấp dịch vụ giao tiếp giữa 2 hosts, con đường giao tiếp tồn tại các chuỗi communication links, bắt đầu tại source host, đi qua một series các router, và kết thúc tại destination host. Chúng ta tiếp tục đi sâu xuống trong protocol stack, từ network layer đến link layer. Chúng ta tự hỏi rằng làm thế nào các packets có thể gửi thông qua individual links  những thứ tạo nên end-to-end communication path. Làm thế nào để network-layer datagrams được đóng gói trong link-layer frames với mục đích vận chuyển thông qua single link ? Hay là các link-layer protocols có thể cung cấp router-router reliable data transfer ? Có thể có các link-layer protocols khác nhau được sử dụng trong các links khác nhau dọc theo communication path ?

Khi thảo luận về link-layer, chúng ta sẽ tìm ra hai kiểu link-layer channels cơ bản khác nhau. Kiểu đầu tiên bao gồm broadcast channels, những gì dễ dàng nhìn thấy trong local area networks (LANs), wireless LANs, các mạng vệ tinh, và hybrid-coaxial cable (HFC) access networks. Đối với broadcast channel, nhiều hosts được kết nối tới cùng một communication channel, và medium access protocol là cần thiết để phối hợp transmissions và tránh collisions giữa các transmited frames. Kiểu thứ hai của link-layer channel đó là point-to-point communication link, giống như là giữa 2 routers hay là giưa residential dial-up modem và ISP router. 

Link Layer : Introduction and Services

Đầu tiên chúng ta sẽ định nghĩa một vài thuật ngữ. Ta gọi các hosts và các routers như là các nodes. Chúng ta còn refer đến communication channels những gì kết nối các nodes liền kề dọc theo communication path là các links. Để cho datagram được transfered trừ source tới des, nó phải được moved trên mỗi individial links trong end-to-end path. Trên một given link, transmiting node đóng gói datagram trong link-layer frame và transmits frame trong link, receiving node sau đó nhận frames và extracts datagram.

Các dịch vụ cung cấp bởi Link Layer
link-layer protocol được dùng để move datagram trên một individial link. link-layer protocol định nghĩa format của packets trao đổi giữa các nodes tại hai đầu của link, cung như là các actions tạo bởi các nodes khi packets được gửi đi và nhận về. Đơn vị của dữ liệu trao đổi bởi link-layer protocol được gọi là frames, mỗi link-layer frame đóng gói network-layer datagram. Chúng ta sẽ xem xét sơ lược về các hành động diễn ra bởi link-layer protocol khi sending và receiving frames bao gồm : phát hiện lỗi, truyền lại, điều khiển luồng, và truy cập ngẫu nhiên. Các ví dụ của link-layer protocols bao gồm Ethernet, 802.11, wireless LANs, token ring, và PPP. 

Trái ngược với network layer có một end-to-end job của việc moving transport-layer segments từ source host đến destination host, link-layer protocol đơn giản hơn, node-to-node job của việc di chuyển network-layer datagrams thông qua một single link trong path. Một đặc điểm quan trọng của link-layer đó là một datagram có thể được carried bởi các link-layer protocols khác nhau trên các links khác nhau trong path. Cho ví dụ, một datagram có thể được carried bởi Ethernet trên first link, PPP trên last link, và link-layer WAN protocol trong intermediate links. Điều quan trọng để note là services cung cấp bởi các link-layer protocols khác nhau along end-to-end path có thể là khác nhau. Cho ví dụ một vài link-layer protocols cung cấp vận chuyển tin cậy trong khi một số khác lại không cung cấp. Do đó network-layer phải có thể hoàn thành end-to-end job của nó khi có sự hiện diện của tập hợp individial link-layer service không đồng nhất.

Để có thể có được insight về link layer  và cách nó liên quan với network layer. Hãy suy ngẫm về transporation analogy. Một travel agen tổ chức một trip cho khách du lịch đi từ Princeton, New Jersey, đi đên Lausanne và Switzerland. Hãng du lịch này quyết đinh chở khách đi từ Princeton đên JFK aiport bằng xe limousine, sau đó từ JFK airport đi máy bay tới Geneva's airport và dùng train để đi tới Lausanne. travel agent sẽ make 3 reservations, một cái chịu trách nhiệm để đưa tourist từ Princeton đến JFK, một airplane company chịu trách nhiệm trong chặng đường từ JFK đến Geneva, và Swiss train chịu trách nhiệm cho việc đưa tourist từ Geneva đến Laussane. Mỗi trong 3 segments của trip là "direct " giữa  2 "adjacent " locations. Chú ý rằng 3 transporation segment được quản lý bởi các công ty khác nhau và sử dụng các transporation modes khác nhau (limousine, plane, train). Mặc dù transporation modes là khác nhau nhưng nhiệm vụ chính của chúng vẫn là vận chuyển tourist từ một location đến location hàng xóm. Trong transporation analogy, tourist là datagram, transporation segment là communication link, transporation mode là link-layer protocol và travel agent là routing protocol.

Mặc dù dịch vụ cơ bản của bất cứ link layer là move datagram từ một node này tới node cận kề nó thông qua một single communication link. Các chi tiết của việc cung cấp dịch vụ có thể khác nhau giữa một link layer  protocol với link layer tiếp theo. Các dịch vụ có thể được cung cấp bởi link-layer protocol bao gồm:
* Framing: hầu hết các giao thức link layer đóng gói mỗi network-layer datagram vào trong link-layer frame trước khi transmission trên một link. Frame chứa data field, những gì mà network-layer datagram được chèn vào, và một số lượng header fields. Cấu trúc của một frame được xác định bởi link-layer protocol. (Frame có thể còn chứa trailer fields; tuy nhiên chúng ta refer cả header và trailer fields như header fields).
* Link access: medium access control (MAC) protocol xác định các luật quy định đối với những frame được transmitted trên link. Đối với point to point links chúng ta có single sender tại một bên của link và single receiver phía còn lại. MAC protocol là đơn giản, sender có thể gửi frame bất cứ khi nào link là idle. Điều hấp dẫn hơn đó là khi nhiều nodes chia sẻ chung một single broadcast link thế nên được gọi là mutiple access problem. Lúc này, MAC protocols phục vụ để phối kết hợp frame transmissions của nhiều nódes.

* Reliable delivery: khi một link-layer protocol cung cấp dịch vụ truyền tải đáng tin, nó đảm bảo rằng truyền tải mỗi network-layer datagram thông qua link mà không bị lỗi. Nhắc lại về TCP, TCP cũng cung cấp dịch vụ truyền tải đáng tin cậy. Tương tự dịch vụ truyền tải đáng tin cậy lớp transport, link-layer reliable dilivery service thường có được những sự báo nhận hay truyền lại. link-layer reliable delivery service thường được sử dụng cho các links truyền tải với tỉ lệ lỗi cao, ví dụ như wireless link, với những thành quả của việc correcting error locally- trên một link nơi xảy ra lỗi. hơn là forcing end-to-end retransmission của dữ liệu như bởi các giao thức lớp ứng dụng hay là truyền tải. Tuy nhiên, link-layer reliable delivery có thể tạo ra những chi phí không cần thiết cho các links có tỉ lệ bit lỗi thấp, bao gồm fiber, coax, và nhiều twisted pair cooper links. Chính vì lí do này, nhiều giao thức link-layer cho mạng có đây không cung cấp dịch vụ vận chuyển tin cậy.

*Flow control: Các nodes tại mỗi bên của link có bộ đêm frame giới hạn. Nó liên quan khi receiving node có thể nhận frames ở tốc độ cao hơn với tốc độ xử lý của nó. Nếu không có flow control, receiver's buffer có thể overflow và frames có thể bị mất. Tương tự như transport layer, link-layer protocol có thể cung cấp điều khiển luồng để ngăn node gửi tại một phía của link overwhelming receiving node node phía bên kia.

* Error Detection: link-layer hardware trong receiving node có thể quyết định sai rằng một bit trong frame là 0 trong khi nó được transmitted như bit 1, và ngược lại. bit erros có thể  là do các tín hiệu  và nhiễu điện. Bởi vì không cần để forward một datagram mà có lỗi trong đó, nhiều link-layer protocols cung cấp cơ chế để tìm ra các bit errors như thế. Nó được thực hiện bởi việc có transmitting node bao gồm error-detection bits trong frame và receiving node perform error check.  Nó giống như internet checksum trong lớp mạng. Error detection thường phức tạp hơn và được implemented bởi hardware.

* Error correction : error correction là tương tự với erroe detection, ngoại trừ việc receiver không chỉ detects khi có bit errors xảy ra trong frame mà còn xác định chính xác tại đâu trong frame có lỗi xảy ra (và sau đó correct các lỗi đó.). Một vài protocols cung cấp link-layer correction cho packet header hơn là toàn bộ packet.

* Half-duplex và full duplex. với full-duplex transmission, các nodes ở cả 2 bên của link có thể transmit packets tại cùng một thời điểm. với half-duplex, một node không thể không transmit và receive tại cùng một thời điểm.

Chúng ta có thể nhận thấy rằng nhiều dịch vụ cung cấp bởi link-layer là tương tự như các dịch vụ cung cấp bởi transport-layer. Cho ví dụ, có link-layer và transport-layer đều cung cấp dịch vụ đánh tin cậy. Mặc dù cơ chế sử dụng để cung cấp reliable delivery trong 2 layers là tương tự, 2 dịch vụ truyền tải là không giống nhau. transport protocol cung cấp dịch vụ tin cậy cho các segments giữa 2 processes trên end-to-end basis; còn đối với link-layer protocol đó là truyền tải frames giữa 2 nodes được kết nối trên single link. Tương tự, có link-layer và transport  protocols có thể cung cấp điều khiển luồng và phát hiện lỗi, đối với transport layer thì các dịch vụ này được thực hiện trên end-to-end basis, trái lại link-layer cung cấp các dịch vụ trên node-to-adjacent-nod

String in C

Các Strings đơn giản chỉ là các mảng kí tự. string trong C có dáng dấp kiểu như :
                           s = "Shatner"
Khi C nhìn một chuỗi kí tự như vậy, nó đọc nó như đọc một mảng các kí tự riêng lẻ.
                           s = {'S', 'h', 'a', 't', 'n', 'e', 'r'}
Mỗi một kí tự trong string là một phần tử của mảng. Chúng ta có thể refer đến các kí tự bằng việc sử dụng index, giống như là s[0], s[1].

Điều gì sẽ xảy ra khi C muốn đọc nội dung của string. Ngày nay, nhiều ngôn ngữ giúp ta "keep track" được kích thước của mảng. C là một ngôn ngữ bậc khá thấp, nó không thể thường xuyên làm việc để có được độ dài của mảng. Nếu C display một string lên screen, nó cần biết được khi nào nó

Thứ Tư, 10 tháng 4, 2013

Kết nối tới cơ sở dữ liệu trong Python

Bài toán đặt ra là làm thế nào để viết một chương trình lấy được dữ liệu từ DB, ví dụ SQL.
Sự khác nhau giữa việc lấy dữ liệu từ một file text thông thường và một file DB chỉ là cách ta truy vấn như thế nào hay thôi. Đối với DB ta cần kết nối đến dữ liệu trong DB.
Xét các đoạn code sau:
import sqlite3
Nhờ câu lênh trên ta import được thư viện hỗ trợ trong SQL
db = sqlite3.connect(surfersDB.sdb)
kết nối đến dữ liệu trong file DB 
db.row_factory = sqlite3.Row
cursor = db.cursor()
cursor.execute("select * from surfers")
rows = cursor.fetchall()
lấy tất cả dữ liệu từ DB, gán dữ liệu đến một biến gọi là "rows"
for row in rows:
process mỗi phần tử trong rows
if row['id'] == 104:
print("ID is " + str(row['id']))
print("Name is " + row['name'])
print("Board-type is " + row['board'])
Tìm kiếm suffer có ID là 104 và in ra dữ liệu nếu match.
cursor.close()
cái này đơn giản chỉ dọn dẹp.

Thứ Tư, 3 tháng 4, 2013

The Hacker’s Best Friend: ctypes

Python module ctypes là một trong các powerful libraries có sẵn cho Python developer. ctypes library cho phép ta gọi các functions trong các thư viện liên kết động DLL và có khả năng mở rộng cho việc tạo các kiểu dữ liệu C phức tạp và các functions tiện ích cho việc thao tác low-level memory.

Using Dynamic Libraries

Bước đầu tiên trong việc tận dụng ctypes là làm thế nào để giải  quyết và truy nhập đến các functions in DLL. DLL là là một compiled binary, được liên kết lúc runtime đến process executable chính. Trên Windows nhiều binary được gọi là DLL, trong khi đó trên Linux chúng được gọi là shared objects (SO). Trong cả hai trường hợp, các binaries sẽ phô ra các functions thông qua exported names, những gì giải quyết với các địa chỉ thực sự trong memory. Thông thường at runtime bạn phải resolve các function addresses theo thứ tự để gọi các functions; Tuy nhiên, với ctypes tất cả các dirty work đã được hoàn thành.

Có 3 cách khác nhau để load dynamic libraries trong ctypes: cdll(), windll(), oledll(). Sự khác nhau giữa 3 cách trên nằm ở cách các functions trong libraries được gọi và kết quả của chúng trả lại giá trị. cdll() method được sử dụng cho việc loading libraries mà export functions sử dụng quy ước chuẩn cdecl. windll() sử dụng stdcall  những gì là quy ước của MS Win32 API, oledll() được tổ chức giống như windll(), tuy nhiên nó được giả sử exported functions trả lại HRESULT  error code, những gì được dành riêng cho error messages trả lại tư MS Component Object Model (COM) functions.

UNDERSTANDING CALLING CONVENTIONS

calling convention mô tả cách làm thế nào một cách hợp lí để gọi một hàm. Nó bao gồm thứ tự: làm thế nào function parameters được cấp phát, những parameters được pushed trên stack hoặc được passed trong registers và làm thế nào stack được unwound khi fuction return. Ta cần hiểu 2 calling conventions đó là : cdecl stdcall . Trong cdel parameters được pushed từ phải sang trái và caller của function chịu trách nhiệm cho clearing các arguments từ stack. Nó được sử dụng bởi hầu hết C systems trên x86.

Chúng ta xét 2 ví dụ để minh họa:

Ví dụ 1: cedl function call
In C
                     int python_rocks(reason_one, reason_two, reason_three)
In x86 Assembly
                     push reason_three
                     push reason_two
                     push reason_one
                     call python_rocks
                     add esp, 12

Các bạn có thể nhận thấy rằng các arguments được passed từ phải qua trái và dòng cuối cùng tăng stack pointer lên 12 bytes (có 3 parameters đến function, và mỗi stack parameter là 4 bytes, do đó 12 bytes), những gì về bản chất clear  các parameters.

Ví dụ 2: stdcall convention, được sử dụng trong Win 32 API
In C
                    int my_socks(color_one, color_two, color_three);
In x86 Assembly
                    push color_three
                    push color_two
                    push color_one
                    call my_socks

Trong trường hợp này ta có thể thấy thứ tự passed các parameters là giống nhau, nhưng stack clearing không được thực hiện bởi caller; my_socks function chịu trách nhiệm cho việc cleaning up trước khi nó return.

Đối với cả 2 conventions điều quan trọng để note là return values được lưu trong thanh ghi EAX.




Thứ Hai, 1 tháng 4, 2013

Giới thiệu Reverse Engineering

Reverse Engineering là gì ?
Reverse Engineering là một process của việc lấy ra (extracting) knowledge hay là bản thiết kế chi tiết từ bất cứ thứ gì man-made.
RE thường được thực hiện để đạt được missing knowledge, ideas, và design philosophy khi những thông tin như vậy là unavailable. Trong một số trường hợp, thông tin được sở hữu bởi một cá nhân nào đó và họ không muốn chia sẻ. Trong một số trường hợp khác thông tin bị lost hay destroyed.

Truyền thống, RE thường taking shrink-wrapped products và physical dissecting chúng để tìm ra những secrets trong design của họ. Những secrets này sau đó được dùng để làm các sản phẩm tương tự hoặc là tốt hơn. Trong nhiều ngành công nghiệp, RE được yêu cầu examining sản phẩm dưới microscope, lấy những phần của nó và tìm hiểu xem mỗi phần trong đó làm những công việc gì.

Cách đây không lâu, RE công bằng mà nói chỉ là popular hobby, practiced bởi một số lượng người đông đảo.

Software RE: Reversing
Software là một trong nhiều công nghệ phức tạp và hấp dẫn xung quanh chúng ta ngày hôm nay và software RE nói về việc mở một program' "box" và nhìn vào bên trong đó. dĩ nhiên, chúng ta không cần bất cứ screwdrivers trên journey này. giống như soft