Tổng quan về SPIN

Một phần của tài liệu Ứng dụng của spin để kiểm chứng sự tuân thủ thể thức tương tác của chương trình (Trang 33)

Bộ công cụ SPIN là công cụ kiểm tra mô hình, là một hệ thống xác minh tính đúng đắn của các chương trình, nó hỗ trợ thiết kế hệ thống đa luồng, hệ thống tương tranh, v.v. SPIN như là một công cụ sử dụng phương pháp hình thức, nó các các đặc điểm:

 Một công cụ trực quan, chương trình sử dụng các ký hiệu để thiết kế đặc tả rõ ràng mà không cần thực hiện cụ thể.

 Là một công cụ mạnh với bộ kí tự rõ ràng dễ mô tả các yêu cầu cần kiểm tra sự đúng đắn của chúng.

 Cung cấp phương pháp luận cho việc thể hiện tính thống nhất, hợp lý phù hợp với các điều kiện cần thỏa mãn [10].

Bộ công cụ SPIN không có các nguyên tắc chung cho kiểm chứng các hệ thống phần mềm khác nhau, vì vậy tùy vào yêu cầu kiểm chứng phần mềm cụ thể mà ta cố gắng đặc tả phần mềm theo một cách thức tương ứng. SPIN yêu cầu các quy tắc hữu hạn để diễn tả các hành vi khác nhau, điều này có nghĩa là tất cả các thuộc tính cần được thỏa mãn của hệ thống đều phải đặc tả hình thức với các ràng buộc về phạm vi, nguồn tài nguyên cần thiết để tính toán kiểm tra mô hình [10]. 3.2.2. Cấu trúc của SPIN

Cấu trúc cơ bản của mô hình SPIN được mô tả trong (Hình 2.2). Mô hình SPIN được bắt đầu bằng việc đặc tả hệ thống tương tranh đa luồng hoặc giải thuật phân tán dưới dạng mô hình bậc cao, sử dụng giao diện đồ họa SPIN. Sau khi được sửa lỗi cú pháp, SPIN sẽ thực hiện việc mô phỏng tương tác cho đến khi đạt độ tin cậy cơ bản để thiết kế các hành vi. SPIN sinh ra một chương trình xác thực theo giải thuật on-the-fly (duyệt nhanh) từ đặc tả mức cao. Bộ xác thực này được biên dịch với sự lựa chọn thời gian biên dịch hợp lý để thực hiện giải thuật giản lược. Nếu có lỗi được phát hiện qua các biến xác nhận lỗi của chương trình, nó sẽ thông báo lại cho bộ mô phỏng và kiểm tra chi tiết khi thực hiện và loại bỏ nguyên nhân gây lỗi [10].

SPIN cũng có thể xác thực trực tiếp phần mềm ở mức thực thi. Sử dụng SPIN như trình điều khiển và một máy logic để xác thực các thuộc tính thời gian ở mức cao. SPIN hoạt động dựa vào phương thức duyệt on-the-fly để xác thực các thuộc tính của hệ thống [10].

Hình 3.2. Cấu trúc mô hình kiểm chứng SPIN

SPIN là một công cụ hỗ trợ tự động gia tăng số lượng các tiến trình hoặc rút gọn số lượng các tiến trình. Nó hỗ trợ các quá trình mô phỏng dựa trên việc chứng minh cục bộ và tổng thể, dựa trên tìm kiếm theo chiều sâu để có thể kiểm soát được kích cỡ bài toán lớn có hiệu quả. SPIN khai thác kỹ thuật giản lược thứ tự từng phần và lưu trữ để tối ưu hóa khi xác thực. Để xác thực một mô hình phần mềm, mô hình đó phải là một mô hình hình thức được xây dựng bằng ngôn ngữ

Promela - ngôn ngữ mô hình hóa của bộ công cụ SPIN. Sử dụng công cụ SPIN

với ngôn ngữ Promela có thể: Mô phỏng tương tác phỏng ngẫu nhiên cho một hệ thống; Xác thực và chứng minh tính đúng đắn so với yêu cầu đặc tả của người sử dụng; Chứng minh sự xấp xỉ của các mô hình hệ thống lớn với việc bao phủ không gian trạng thái.

Cấu trúc và cách thức hoạt động của bộ công cụ SPIN dùng để kiểm tra mô hình có thỏa mãn hay không thỏa mãn tính chất có một số bước cụ thể. Tuy nhiên trong nội dung của luận văn này chỉ xét đến khía cạnh kiểm chứng sự tuân thủ hoặc không tuân thủ thể thức tương tác của chương trình nên ta thực hiện hai bước: mô hình hóa thể thức tương tác của chương trình bằng một tiến trình đồng thời mô hình hóa thể thức tương tác của một thành phần cũng bằng một tiến trình trong SPIN, hai tiến trình này chạy song song và sử dụng một kênh dữ liệu chung; thực hiện chạy SPIN để xác minh (verification). Kết quả sẽ được báo cáo trong

Thông báo lỗi cú pháp

Phân tích cú pháp Giao diện SPIN

Phân tích cú pháp LTL và dịch

Kiểm tra xác thực

Tối ưu bộ kiểm tra mô hình

Thực hiện xác thực on-the-fly Phản ví dụ

cửa sổ pan.out của ISPIN ngay sau khi chạy xác minh: nếu không có deadlock

(không báo Invalid EndState depth ( )) thì chương trình tuân thủ thể thức tương tác của thành phần, nếu có deadlock (báo Invalid endState depth ( )) thì thành phần không tuân thủ thể thức tương tác của chương trình. Cần phải yêu cầu bên thiết kế xây lại thể thức của chương trình.

2.2.3. Công cụ ISPIN

Bộ công cụ ISPIN có giao diện thân thiện, dễ sử dụng trong quá trình thực hiện kiểm chứng mô hình [19].

Hình 3.3. Giao diện ISPIN soạn thảo mã nguồn mô hình kiểm chứng

Công cụ ISPIN có cửa sổ để soạn thảo và chỉnh sửa chương trình (Hình 2.3)

khá đơn giản. Sau khi soạn thảo ta kiểm tra cú pháp với Tab Syntax Check. Kiểm tra

cú pháp phải được thực hiện nhằm chỉnh sửa cú pháp soạn thảo sai. Ngoài ra, thực

hiện Tab Redundancy Check nhằm xác định các thành phần không liên quan, sự dư

thừa của một số thành phần trong mô hình.

Với Tab Simulate/Replay là Tab quan trọng trong ISPIN, cửa sổ giao diện (Hình 3.4), trong cửa sổ của Tab này cần một số thiết lập:

Random, with seed: Khởi đầu ngẫu nhiên. (adsbygoogle = window.adsbygoogle || []).push({});

Interactive (for resolution of all nondeterminism): Tương tác

Guided, with trail: Đường dẫn dấu vết.

Initial steps skipped: Bỏ qua bước khởi tạo

Maximum number of steps: Số bước tối đa thiết lập.

Message Sequence Chart (MSC): Cung cấp quá trình giao tiếp của tiến trình

theo thời gian được thiết lập như thời gian trễ (delay) hoặc cách trình bày trên cửa sổ văn bản.

Trong Tab này quan trọng nhất là thực hiện (Re)Run và ta có thể quan sát

được MSC cùng sự thực hiện của dòng lệnh trên các cửa sổ msc.ps và simulation output cùng các bước thực hiện của mô hình.

Hình 3.4. Thiết lập thông số khi thực hiện Simulate/Replay.

Với Tab Verification là Tab ứng dụng cơ bản cần thiết trong nội dung này. Giao diện (Hình 3.5) với thiết lập quan trọng như sau:

Safety: Độ an toàn

+ Invalid endstates(deadlock): Trạng thái cuối không hợp lệ. + Assertion violation: Vi phạm khẳng định.

Ngoài ra có thể thiết lập: Depth first search (độ sâu tìm kiếm đầu tiên).

Report unreachable code: mã báo cáo không thể truy cập.

Sau khi Run chương trình thì kết quả xuất hiện trên cửa sổ pan.out, trong cửa

sổ này sẽ báo cáo có hoặc không deadlock (bế tắc) và báo cáo có hoặc không có violation (lỗi). Từ báo cáo này có thể kết luận được quá trình kiểm chứng.

3.3. Ngôn ngữ Promela

Để kiểm chứng thì cần xây dựng mô hình để mô phỏng chương trình trong

SPIN. Ngôn ngữ Promela giúp cho việc xây dựng mô hình trong SPIN một cách

rõ ràng, dễ hiểu và có được mô hình trực quan.

3.3.1. Tổng quan về Promela

Promela (Protocol meta language) là một ngôn ngữ mô hình hóa trong

SPIN, nó có thể trừu tượng hóa các giao thức trong các hệ thống tương tranh đa

luồng, hệ thống phân tán, v.v. Ngôn ngữ Promela trừu tượng hóa các giao thức

tương tác truyền dữ liệu, các thành phần trong phần mềm, hệ thống chuyển mạch, phần mềm điều khiển và có thể kiểm chứng sự tương tác của các giao thức này.

Quá trình xác thực bao gồm: Xây dựng mô hình trong SPIN bằng Promela,

mỗi mô hình được xác thực với SPIN dưới nhiều dạng khác nhau của môi trường giả định như: có sự tương tác giữa các giao thức với nhau hoặc không, có sự tuân thủ thể thức tương tác, hoặc như sự mất gói tin, các gói tin bị lặp v.v.

3.3.2. Chương trình Promela (adsbygoogle = window.adsbygoogle || []).push({});

Một chương trình Promela chứa các tiến trình (processes), biến (variable),

hằng…với các kiểu dữ liệu tùy ý, các tiến trình đặc tả hành vi của hệ thống.

Chương trình Promela có thể chứa các kênh thông điệp (message channel). Một chương trình Promela cơ bản:

 Khai báo kiểu.  Khai báo biến.  Khai báo tiến trình.  Tiến trình Init.

// Các khai báo

mtype = {MSG, ACK};/*khai bao kieu*/ chan toS = ... /*khai bao kenh*/

chan toR = ...

bool varbool; /*khai bao bien*/ // Một tiến trình

lenh_1; lenh_n }

Init { /* Tien trinh khoi tao*/ ...

}

3.3.3. Tiến trình

Một tiến trình được khai báo bằng từ khóa proctype. Một chương trình

Promela có thể có một hoặc nhiều tiến trình, mỗi tiến trình chứa một hoặc nhiều các

câu lệnh và mỗi tiến trình có thể có tham số hoặc không có tham số. Tuy nhiên có

một chú ý quan trọng đó là tiến trình có thể được khai báo với từ khóa active thì được gán một giá trị pid (process id) duy nhất và có thể chạy chương trình.

Active proctype p( ){

Lenh_1;

……..

Lenh_n

}

Với một tiến trình mà khai báo không có từ khóa active thì sẽ không được cấp pid và nó chưa thể chạy.

proctype p( ){

Lenh_1;

……..

Lenh_n

}

Thân của tiến trình chứa một dãy các câu lệnh, để ngăn cách giữa các câu lệnh

tuần tự thì Promela sử dụng dấu ; hoặc dấu ->. Hai dấu hiệu phân cách này tương

đương nhau, trong đó dâu -> thể hiện mối quan hệ cho hai lệnh trước và sau dấu này, (adsbygoogle = window.adsbygoogle || []).push({});

nó như quan hệ nếu…thì. Câu lệnh cuối cùng trong một tiến trình không có dấu.

Các tiến trình có thể thực hiện đồng thời với các hành vi độc lập, nó có thể liên kết với nhau bởi các biến chung toàn cục hoặc sử dụng kênh chia sẻ biến chung. Mỗi tiến trình đều có trạng thái cục bộ và có thể có các biến cục bộ.

Ví dụ:

Proctype A{

byte tmp;

(state == 1) -> tmp = state; tmp = tmp + 1; state = tmp }

3.3.4. Tiến trình Init và Run

Một số tiến trình có thể được khai báo mà không có từ khóa active nó không được cấp pid và nó chưa thể chạy. Muốn chạy nó thì phải khai báo thêm

Run như sau:

proctype P( ){ } Run P ( );

Tiến trình Init là một tiến trình khởi tạo, nó được thực thi ngay khi chạy chương trình trong SPIN. Các tiến trình khai báo sau định nghĩa Proctype chỉ là

khai báo tiến trình, do đó khi chạy tiến trình này chưa thực thi nếu đằng trước

Proctype không khai báo Active hoặc Run. Tuy nhiên, nếu không khai báo Active

và Run, để chạy các tiến trình này thì ta khai báo Run các tiến trình trong Init.

proctype P( ){ } proctype Q( ){ } Init { Run P( ); Run Q( ); }

Với câu lệnh Run, có thể áp dụng ở bất cứ tiến trình nào không nhất thiết

phải ở tiến trình khởi tạo. Các tiến trình có thể thực hiện xen kẽ nhau, không nhất thiết kết thúc tiến trình này mới đến tiến trình tiếp theo.

Hầu hết các ngôn ngữ lập trình đều yêu cầu khai báo biến trước khi sử dụng

chúng để tính toán trong chương trình. Với ngôn ngữ Promela là biến thể của ngôn

ngữ C thì điều này cũng hoàn toàn đúng, nó cũng yêu cầu khai báo biến trước khi sử

dụng chúng. Trong Promela, biến được khai báo tên biến ngay sau kiểu biến. Đây là

cách định nghĩa kiểu biến thường thấy trong ngôn ngữ C [1].

Ví dụ:

byte var1; short var2 = 1;

Tất cả các biến được khởi tạo mặc định là 0. Tuy nhiên, nên khởi tạo ngay khi khai báo biến.

Gán giá trị cho biến thì có thể sử dụng các lệnh như sau:

Lệnh gán: var1 = 1;

Khai báo kết hợp khởi tạo: Short var2 = 1;

Câu lệnh kiểm tra điều kiện: i * s + 5 ==27;

Biến trong Promela có thể là biến toàn cục hoặc biến cục bộ tùy thuộc vào (adsbygoogle = window.adsbygoogle || []).push({});

vị trí khai báo biến. Một biến cục bộ được khai báo trong một tiến trình, phạm vi hoạt động của biến đó chỉ nội trong tiến trình đó. Khi tiến trình đó kết thúc thì biến đó cũng không còn tồn tại.

3.3.6. Kiểu dữ liệu trong Promela

3.3.6.1. Kiểu dữ liệu cơ bản

Promela không tồn tại một số kiểu dữ liệu như: real, char, string, float như

một số ngôn ngữ khác. Kiểu dữ liệu cơ bản của Promela được thể hiện trong bảng

(Bảng 2.1).

Bảng 3.1 Kiểu dữ liệu cơ bản

Tên kiểu Giá trị Kích thước(bits)

bit, bool byte short int unsigned 0, 1, false, true 0..255 -32786..32767 -231..231-1 0..2n-1 18 16 32 ≤ 32

3.3.6.2. Kiểu dữ liệu có cấu trúc a) Kiểu mảng a) Kiểu mảng

Khai báo:

int arrtb[max];

Dữ liệu kiểu mảng được đánh chỉ số bắt đầu từ 0, như vậy phần tử của mảng theo khai báo trên sẽ là:

arrtb[0], arrtb[1], …, arrtb[max-1];

Ví dụ:

byte state[10]; //state[0],…,state[9];

b) Kiểu bản ghi

Kiểu bản ghi được khai báo như sau:

typedef Record {

byte var1; short var2; }

c) Kiểu liệt kê

Kiểu liệt kê là kiểu tập hợp các hằng số được khai báo như sau:

mtype = { LINE_CLEAR, TRAIN_ON_LINE, LINE_BLOCKED};

Chú ý: Một chương trình chỉ chứa một kiểu liệt kê và nó phải được sử dụng là toàn cầu (dùng chung).

Ngoài ra, Promela có một kiểu dữ liệu khác thường được sử dụng đó là dữ

liệu kiểu kênh. Kiểu dữ liệu này sẽ được đề cập riêng (phần 2.3.12). 3.3.7. Toán tử, dịnh danh, hằng và biểu thức

a) Toán tử

Chương trình Promela có các toán tử tương tự như các toán tử trong ngôn ngữ lập trình C. Liệt kê các toán tử (Bảng 2.2) trong Promela, nó có độ ưu tiên

thực hiện giảm dần từ trên xuống [2].

Bảng 3.2. Toán tử trong Promela (adsbygoogle = window.adsbygoogle || []).push({});

Thứ tự Toán tử Tên 1 2 3 4 5 ( ) [ ] . ! ~

Dấu ngoặc đơn Chỉ số mảng Lựa chọn trường Phủ định

6 7 8 9 10 11 12 13 14 15 16 17 18 ++, -- *, /, % +, - <<, >> <, <=, >, >= = =, != & ^ | && || (→ : ) = Tăng, giảm

Nhân, chia, chia lấy dư Cộng, trừ

Dịch bit trái, dịch bit phải Phép toán so sánh số học

Tương đương, không tương đương Và bit

Hoặc loại trừ bit Hoặc gộp bit Và (logic) Hoặc logic

Biểu thức có điều kiện Phép gán

b) Định danh

Định danh trong Promela có thể là một chữ cái, một ký tự, một dấu chấm

hay dấu gạch dưới, theo sau là một dấu hai chấm (:). Định danh giúp cho việc khi một tính toán của chương trình cần thiết phải chyển đến một vị trí cụ thể. Vị trí này được đặt định danh, nó giống như việc đánh dấu vị trí truy cập.

c) Hằng

Hằng số là một chuỗi ký tự đại diện cho số nguyên, số thập phân. Hằng số được xác định bởi mtype, hoặc thông qua một định nghĩa macro. Hằng số luôn được khai báo ở đầu chương trình. Ví dụ:

# define maxx 50

d) Biểu thức

Biểu thức trong Promela được xây dựng từ các biến, hằng, toán tử. Ví dụ các biểu thức như sau:

x = y + z; // phép gán

Hoặc:

z ++; // phép tăng

3.3.8. Câu lệnh trong Promela

Trong Promela, các câu lệnh được thi hành một cách bình đẳng, nó không

có sự phân biệt giữa các lệnh điều kiện và lệnh thông thường. Có các lệnh thi hành (executable) hoặc lệnh được trì hoãn tạm thời để chờ thực hiện tiếp theo một

điều kiện nào đó tùy thuộc vào trạng thái của hệ thống. Các câu lệnh điều kiện chỉ được thi hành khi nó thỏa mãn điều kiện, hay điều kiện của nó là True. Với lệnh thi hành thì nó thực hiện ngay lập tức khi gọi lệnh [2].

Một câu lệnh theo sau biểu thức logic được thi hành khi biểu thức có giá trị là true (giá trị biểu thức khác 0).

Một số câu lệnh trong Promela:

o Lệnh Printf: đây là câu lệnh thi hành. Nó không có tác dụng trong việc

đánh giá để xác thực điều gì đó của chương trình.

o Lệnh assert(<bt>): lệnh này luôn là lệnh thi hành. Khi <bt> có giá trị sai,

chương trình sẽ thoát và ghi nhận lỗi vi phạm. Câu lệnh này dùng để kiểm

(adsbygoogle = window.adsbygoogle || []).push({});

Một phần của tài liệu Ứng dụng của spin để kiểm chứng sự tuân thủ thể thức tương tác của chương trình (Trang 33)