WorksheetsCâu hỏi về lập trình socket và đa luồng
Total questions: 73
Worksheet time: 37mins
Câu 1: Lập trình truyền thông với socket cho phép:
Quản lý bộ nhớ
Đọc và ghi file
Tối ưu hóa bộ nhớ
Truyền thông giữa các máy trong mạng
Câu 2: Trong lập trình đa luồng với pthread, hàm nào được sử dụng để theo dõi trạng thái kết thúc của một luồng và thu hồi tài nguyên khi luồng đó kết thúc?
pthread_detach()
pthread_join()
pthread_create()
pthread_exit()
Câu 3: Hai phương thức SOCK_STREAM và SOCK_DGRAM lần lượt tương ứng với giao thức tầng vận chuyển nào?
IPv4 và IPv6
TCP và UDP
UDP và TCP
HTTP và FTP
Câu 4: Trong lệnh tạo socket: sockfd = socket(AF_INET, SOCK_STREAM, 0); Tham số nào chỉ loại giao thức (protocol) khi tạo socket và giá trị của nó là gì?
Tham số SOCK_STREAM, giá trị là 1
Tham số 0, giá trị là Protocol mặc định
Tham số AF_INET, giá trị là IPv4
Tham số SOCK_STREAM, giá trị là 0
Câu 5: Từ khóa AF_UNIX trong lập trình socket được dùng làm gì?
Kết nối mạng LAN
Kết nối trong cùng hệ thống (local)
Kết nối trên mạng IPv6
Kết nối trên mạng IPv4
Câu 6: Trong lập trình đa luồng, hàm pthread_mutex_lock() được sử dụng để làm gì?
Hủy mutex sau khi hoàn thành công việc
Khóa mutex để ngăn các luồng khác truy cập vào tài nguyên dùng chung
Mở khóa mutex để cho phép các luồng khác truy cập tài nguyên
Khởi tạo một mutex để đồng bộ hóa luồng
Câu 7: Trong lập trình socket, hàm listen() thường được sử dụng để làm gì?
Cho phép server lắng nghe các yêu cầu kết nối từ client
Cho phép client lắng nghe kết nối từ server
Đóng một socket đã tạo
Tạo kết nối tới server
#include <stdio.h>
#include <pthread.h>
#define n 100000000
void* DemSoLe(void* arg) {
long dem = 0;
for (long i = 1; i <= n; i++) {
if (i % 2 != 0) dem++;
}
printf("%ld\n", dem);
return NULL;
}
int main() {
pthread_t thread_id;
pthread_create(&thread_id, NULL, DemSoLe, NULL);
pthread_join(thread_id, NULL); // Dòng này bị xóa
return 0;
}
Giả sử trong đoạn mã trên, dòng pthread_join(thread_id, NULL); bị xóa đi. Điều gì sẽ có khả năng xảy ra khi chạy chương trình?
Chương trình sẽ không thể tạo luồng mới để thực hiện công việc.
Chương trình sẽ chạy bình thường và in ra kết quả mà không gặp vấn đề gì.
Tài nguyên của luồng sẽ không được giải phóng ngay cả khi luồng đó đã hoàn thành, không in ra kết quả.
Chương trình sẽ rơi vào vòng lặp vô hạn và không bao giờ kết thúc.
#include <stdio.h>
#include <pthread.h>
void* print_hello(void* arg){
printf("Hello Thread\n");
return NULL;
}
int main() {
pthread_t thread_id;
pthread_create(&thread_id, NULL, print_hello, NULL);
pthread_join(thread_id, NULL);
return 0;
}
Câu hỏi:
Trong đoạn mã trên, chức năng chính của lệnh pthread_create là gì?
Đợi luồng phụ kết thúc trước khi tiếp tục thực hiện chương trình.
Kiểm tra xem có lỗi xảy ra trong hàm print_hello() hay không.
Tạo một biến pthread_t để lưu trữ số lượng luồng.
Tạo một luồng mới để thực hiện hàm print_hello()
Cho demso.c chứa mã nguồn chương trình C như sau:
#include <stdio.h>
#include <pthread.h>
int dem = 0;
void* DemSo() {
int i;
for (i = 0; i < 10000; i++) {
dem++;
}
return NULL;
}
void main() {
pthread_t thread0, thread1, thread2;
pthread_create(&thread0, NULL, DemSo, NULL);
pthread_create(&thread1, NULL, DemSo, NULL);
pthread_create(&thread2, NULL, DemSo, NULL);
pthread_join(thread0, NULL);
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
printf("%d\n", dem);
}
Khi chạy chương trình này, giá trị nào dưới đây có thể là kết quả in ra của biến dem?
Một số giá trị ngẫu nhiên nằm trong khoảng từ 10000 đến 20000)
Kết quả sẽ luôn là 0
10000
20000
Cho demso.c chứa mã nguồn chương trình C như sau:
#include <stdio.h>
#include <pthread.h>
int dem = 0;
void* DemSo() {
int i;
for (i = 0; i < 10000; i++) {
dem++;
}
return NULL;
}
void main() {
pthread_t thread0, thread1, thread2;
pthread_create(&thread0, NULL, DemSo, NULL);
pthread_create(&thread1, NULL, DemSo, NULL);
pthread_create(&thread2, NULL, DemSo, NULL);
pthread_join(thread0, NULL);
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
printf("%d\n", dem);
}
Câu hỏi:
Nguyên nhân nào khiến kết quả của biến dem có thể khác nhau mỗi lần chạy chương trình?
Giá trị của biến dem không được khởi tạo đúng cách.
Hàm pthread_join không đợi hai luồng hoàn thành.
Hàm pthread_create không được gọi đúng cách.
Thiếu đồng bộ hóa khi cả hai luồng cùng truy cập và thay đổi biến dem.
Cho demso.c chứa mã nguồn chương trình C như sau:
#include <stdio.h>
#include <pthread.h>
int count = 0;
pthread_mutex_t lock;
void* increase_count() {
int i;
for (i = 0; i < 10000; i++) {
pthread_mutex_lock(&lock);
count++;
pthread_mutex_unlock(&lock);
}
return NULL;
}
void main() {
pthread_t thread0, thread1, thread2;
pthread_mutex_init(&lock, NULL);
pthread_create(&thread0, NULL, increase_count, NULL);
pthread_create(&thread1, NULL, increase_count, NULL);
pthread_create(&thread2, NULL, increase_count, NULL);
pthread_join(thread0, NULL);
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
printf("Count = %d\n", count);
}
Mục đích của pthread_mutex_lock(&lock); và pthread_mutex_unlock(&lock); trong hàm increase_count() là gì?
Để tăng tốc độ thực thi của chương trình.
Để dừng chương trình khi count đạt đến 10000.
Để tạo ra các luồng mới.
Để đảm bảo rằng chỉ có một luồng có thể truy cập và thay đổi biến count tại một thời điểm.
Cho demso.c chứa mã nguồn chương trình C như sau
#include <stdio.h>
#include <pthread.h>
int count = 0;
pthread_mutex_t lock;
void* increase_count() {
int i;
for (i = 0; i < 10000; i++) {
pthread_mutex_lock(&lock);
count++;
pthread_mutex_unlock(&lock);
}
return NULL;
}
void main() {
pthread_t thread0, thread1;
pthread_mutex_init(&lock, NULL);
pthread_create(&thread0, NULL, increase_count, NULL);
pthread_create(&thread1, NULL, increase_count, NULL);
pthread_join(thread0, NULL);
pthread_join(thread1, NULL);
printf("Count = %d\n", count);
}
Giá trị in ra của count khi chạy chương trình này sẽ là gì?
0
10000
Giá trị không xác định
20000
Cho server.c chứa mã nguồn chương trình C như sau:
len = sizeof(cli);
connfd = accept(sockfd, (SA *) &cli, &len);
if (connfd < 0)
{
printf("server accept failed...\n");
exit(0);
}
else
printf("server accept the client...\n");
Câu hỏi: Trong đoạn mã connfd = accept(sockfd, (SA *) &cli, &len);, connfd chứa thông tin gì?
Địa chỉ IP của client.
Mô tả của socket client.
Mô tả của socket mới để giao tiếp với client.
Mô tả của socket server.
Phương thức để tạo một luồng mới trong C sử dụng thư viện pthread là gì?
pthread_new()
pthread_thread()
pthread_create()
pthread_init()
Câu lệnh nào được sử dụng để tạo ra một mutex trong lập trình luồng?
pthread_mutex_create()
pthread_mutex_lock()
pthread_mutex_init()
pthread_mutex_unlock()
Trong lập trình truyền thông, số hiệu cổng (port number) dùng để?
Định danh địa chỉ IP
Lắng nghe kết nối
Phân biệt các ứng dụng trên cùng một máy
Tạo socket
Khi một luồng đang giữ một mutex và không giải phóng nó, các luồng khác cần tài nguyên đó sẽ làm gì?
Chờ đến khi mutex được mở khóa
Khóa thêm lần nữa
Hủy mutex đó
Tự động truy cập tài nguyên
Trong lập trình socket, SOCK_STREAM dùng để chỉ loại kết nối nào?
Kết nối tin cậy, tuần tự
Gửi và nhận dữ liệu thô
Kết nối không tin cậy, không tuần tự
Truyền thông giữa các máy tính qua giao thức HTTP
: Cho một chương trình C sử dụng Thread (đa luồng) trong file program.c có nội dung như sau:
#include <stdio.h>
#include <pthread.h>
void* print_hello(void* arg){
printf("Hello Thread\n");
return NULL;
}
int main(){
pthread_t thread_id;
pthread_create(&thread_id, NULL, print_hello, NULL);
pthread_join(thread_id, NULL);
return 0;
}
Lệnh nào sau đây được dùng để biên dịch chương trình này một cách chính xác?
gcc program.c -o program
gcc program.c -o program -pthread
gcc program.c -o program -lthread
gcc program.c -pthread -o program
Giả sử trong đoạn mã trên, dòng pthread_join(thread_id, NULL); bị xóa đi. Điều gì sẽ có khả năng xảy ra khi chạy chương trình?
Chương trình sẽ rơi vào vòng lặp vô hạn và không bao giờ kết thúc.
Chương trình sẽ không thể tạo luồng mới để thực hiện công việc.
chạy bình thường và in ra kết quả mà không gặp vấn đề gì.
Tài nguyên của luồng sẽ không được giải phóng ngay cả khi luồng đó đã hoàn thành, không in ra kết quả.
Trong chương trình này, lệnh pthread_mutex_init(&lock, NULL); có vai trò gì?
Khởi tạo các luồng thread0 và thread1.
Khởi tạo biến count với giá trị ban đầu là 0.
Khởi tạo mutex lock để sử dụng cho đồng bộ hóa luồng.
Gọi hàm increase_count()
Đoạn mã nào cần thêm vào cuối hàm để giải phóng tài nguyên của mutex look
pthread_mutex_unlock(&lock);
pthread_mutex_destroy(&lock);
pthread_exit(NULL);
pthread_cancel(thread0); pthread_cancel(thread1);
Mục đích của trình biên dịch chéo (cross-compiler) là gì?
Tăng tốc độ khởi động hệ thống
Tối ưu hóa file hệ thống root
Biên dịch mã nguồn cho kiến trúc phần cứng khác với máy host
Cấu hình phần cứng của board
Yêu cầu dung lượng trống tối thiểu của đĩa cứng trên máy tính khi cài đặt môi trường phát triển cho board nhúng là:
20GB
10GB
15GB
25GB
U-boot là gì trong quá trình phát triển hệ điều hành cho board nhúng?
Trình biên dịch kernel
Trình tải khởi động (bootloader)
Trình biên dịch các ứng dụng người dùng
Bộ công cụ xây dựng kernel
Lệnh nào dưới đây trên hệ điều hành Linux được sử dụng để kiểm tra địa chỉ IP của board nhúng khi kết nối với mạng?
ipconfig
ls
ifconfig
netstat
Để điều khiển các thiết bị ngoại vi trên board nhúng, cần phải cài đặt:
Phần mềm văn phòng
Ứng dụng nghe nhạc
Trình điều khiển (driver) tương ứng
Trình duyệt web
Công cụ toolchain trong quy trình biên dịch hệ điều hành nhúng có vai trò chính là:
Cung cấp trình biên dịch chéo GCC
Cung cấp các thư viện hệ thống
Phân tích lỗi hệ thống
Biên dịch mã thành mã nguồn mở
Trong quy trình biên dịch hệ điều hành nhúng, bộ công cụ toolchain cung cấp những gì?
Bộ công cụ để tạo các file nén
Bộ công cụ cài đặt hệ điều hành
Trình biên dịch, trình liên kết và các công cụ hỗ trợ biên dịch mã nguồn
Trình cài đặt bootloader
Chức năng của mkimage trong quy trình biên dịch hệ điều hành nhúng là gì?
Tạo hình ảnh bộ nhớ
Biên dịch mã nguồn thành file thực thi
Chạy hệ điều hành trên board nhúng
Tạo file image cho kernel và bootloader
Sau khi biên dịch hệ điều hành và kernel, để cài đặt lên board nhúng, bước tiếp theo là gì?
Chạy ứng dụng trên máy tính chủ
Tạo hệ thống file nhúng
Cài đặt bộ cài hệ điều hành vào bộ nhớ flash của board nhúng
Biên dịch lại kernel
Công cụ nào thường được sử dụng để quản lý và biên dịch mã nguồn cho hệ điều hành nhúng?
Makefile
Visual Studio
Eclipse
PyCharm
Kiểm tra tính tương thích của kernel sau khi biên dịch với phần cứng thiết bị sẽ giúp gì?
Đảm bảo tất cả các driver phần cứng hoạt động ổn định
Kiểm tra khả năng kết nối internet của thiết bị
Kiểm tra giao diện người dùng của hệ điều hành
Kiểm tra tốc độ của các ứng dụng
Trước khi tạo uImage bằng mkimage, bạn cần cài đặt công cụ hỗ trợ. Trên hệ điều hành Ubuntu, lệnh nào sau đây là đúng để cài đặt công cụ cần thiết?
sudo install mkimage
sudo apt install uboot-tools
apt-get uboot-image
apt-get install mkimage-tools
Bạn cần chạy file Makefile có tên Makefile-build để thực hiện mục tiêu all. Lệnh nào sau đây là đúng?
sudo make all Makefile-build
make -f Makefile-build all
make build all
make Makefile-build all
Bạn cần cấu hình file uEnv.txt để khởi động board nhúng từ thẻ microSD với các tham số console, netargs, netboot, và uenvcmd. Cấu hình nào dưới đây là đúng?
console=ttyS0,9600n8 netargs=setenv bootargs console=ttyO2,9600n8 root=/dev/mmcblk1p1 rw rootfstype=ext4 rootwait netboot=echo Booting from eMMC...; load mmc 0:1 ${loadaddr} uImage; load mmc 0:1 ${fdtaddr} am335x-boneblack.dtb; run netargs; bootm ${loadaddr} ${fdtaddr} uenvcmd=run netboot 1
console=ttyO0,115200n8 root=/dev/mmcblk0p2 ro rootfstype=ext4 autoload=no uenvcmd=run loadimage
console=ttyO0,115200n8 netargs=setenv bootargs console=ttyS0,115200n8 root=/dev/sda1 rw rootfstype=ext4 rootwait netboot=echo Booting from USB...; load usb 0:1 ${loadaddr} uImage; load usb 0:1 ${fdtaddr} am335x-boneblack.dtb; run netargs; bootm ${loadaddr} ${fdtaddr}
Khi build Root File System (RFS) cho board nhúng, bạn cần giải nén file rootfs.tar vào một thư mục trên hệ thống và sao chép các file từ thư mục đó vào thẻ nhớ. Câu lệnh nào dưới đây là đúng?
tar -xvf rootfs.tar -C /mnt/rfs và cp -r /mnt/rfs/* /mnt/sdcard/
tar -xvf rootfs.tar -C /media/sdcard/RFS/ và cp -r /mnt/rfs/* /media/sdcard/
tar -xvf rootfs.tar -C /mnt/rfs và cp -r /mnt/rfs/* /media/sdcard/
tar -xvf rootfs.tar -C /mnt/rfs và cp -r /mnt/rfs/* /media/sdcard/RFS/
Để điều khiển các thiết bị ngoại vi trên board nhúng, cần phải cài đặt:
Ứng dụng nghe nhạc
Trình duyệt web
Trình điều khiển (driver) tương ứng
Phần mềm văn phòng
Lệnh nào dưới đây được sử dụng để khởi động lại hệ điều hành trên board nhúng?
exit
shutdown
reboot
powero
Vai trò chính của kbuild trong hệ thống phần mềm là:
Cài đặt phần mềm
Biên dịch kernel
Tạo môi trường phát triển
Biên dịch các thư viện hệ thống
Quy trình biên dịch hệ điều hành nhúng trên board nhúng bắt đầu từ bước nào?
Cài đặt bootloader
Cài đặt toolchain
Biên dịch kernel
Tạo file hệ thống
Bootloader trên board nhúng có vai trò gì trong quy trình khởi động hệ điều hành?
Khởi động kernel từ bộ nhớ
Biên dịch hệ điều hành
Cài đặt kernel
Tạo bộ nhớ ảo
Sau khi biên dịch kernel cho board nhúng, bạn cần lưu các file cần thiết vào thẻ nhớ để board có thể khởi động. Câu nào dưới đây là đúng khi chỉ định các file cần thiết cho việc khởi động?
Image, am335x-boneblack.dtb, uEnv.txt
vmlinuz, dtb, boot.cmd
kernel.img, deb, Env.txt
uImage, boot.scr
Trên ảnh chưa chắc chắn
Dùng fdisk tạo phân vùng FAT32 1000 MB và ext3 50 MB, sau đó sử dụng lệnh mkfs.fat32 và mkfs.ext3 để định dạng.
B. Sử dụng gparted để tạo phân vùng ext3 1000 MB và phân vùng FAT32 50 MB, rồi gần nhân BOOT cho phân vùng đầu tiên và RFS cho phân vùng thứ hai.
Sử dụng GParted để tạo phân vùng FAT32 (1000 MB) và phân vùng ext3 (50 MB), sau đó gần nhân BOOT cho phân vùng đầu tiên và RFS cho phân vùng thứ hai.
Dùng parted tạo phân vùng FAT32 1000 MB và ext3 50 MB, sau đó sử dụng lệnh mkfs.fat32 cho phân vùng BOOT và mkfs.ext3 cho phân vùng RFS.
Khi module kernel được nạp, thông tin về nó có thể được kiểm tra bằng lệnh nào?
lsmod
rmmod
modprobe
insmod
Lệnh nào được sử dụng để nạp một module vào kernel?
dmesg
rmmod
make
insmod
Lệnh nào được sử dụng để tháo module ra khỏi kernel?
insmod
modprobe
rmmod
lsmod
Khi gọi hàm dmesg, điều gì sẽ xảy ra?
Nó nạp một module vào kernel.
Nó ghi dữ liệu vào file.
Nó trả về tất cả các thông tin hệ thống trong bộ nhớ.
Nó hiển thị tất cả các thông báo hoặc lỗi trong kernel log.
Hai hàm module_init() và module_exit() dùng để làm gì?
Định nghĩa hàm khởi tạo và hủy driver khi nạp và gỡ bỏ
Định nghĩa các hàm đọc/ghi của driver
Điều khiển quá trình khởi động hệ thống
Cấp phát bộ nhớ cho driver
Lệnh nào được sử dụng để tháo module hello.ko khỏi kernel?
$ sudo rmmod hello.ko
$ dmesg
$ make clean
$ sudo insmod hello.ko
Lệnh nào được sử dụng để lắp module hello.ko vào kernel?
$ sudo insmod hello.ko
$ modinfo hello.ko
$ make
$ dmesg
Câu nào dưới đây mô tả chính xác về tệp .ko trong hệ điều hành Linux?
Tệp .ko là tệp chứa mã nguồn của kernel module.
Tệp .ko là tệp nhị phân được tạo ra khi biên dịch kernel module và có thể được tải vào kernel.
Tệp .ko là tệp thực thi của hệ điều hành Linux.
Tệp .ko là tệp cấu hình hệ thống của kernel.
Trong quá trình biên dịch một chương trình hoặc kernel module, lệnh make clean có tác dụng gì?
Hiển thị thông tin về kernel module
Cài đặt kernel module vào hệ thống
Chạy chương trình sau khi biên dịch xong
Xóa các tệp tạm thời và tệp đã biên dịch trước đó
Bạn đã biên dịch một kernel module có tệp là hello.c với Makefile có nội dung như sau: make obj-m += hello.o all: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules clean: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean Lệnh nào sau đây được dùng để biên dịch kernel module hello.o?
$ make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
$ make hello.o
$ sudo insmod hello.ko
$ make
Bạn đã biên dịch một kernel module có tệp là hello.c với Makefile có nội dung như sau:
make
obj-m += hello.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
Lệnh nào sau đây được dùng để biên dịch kernel module hello.o?
A. $ make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
B. $ make hello.o
C. $ sudo insmod hello.ko
D. $ make/
Câu 11: Cho tệp kernel_module.c chứa mã nguồn chương trình C như sau:
#include <linux/module.h>
#include <linux/kernel.h>
int __init hello_module(void)
{
printk(KERN_INFO "Hello\n");
return 0;
}
void __exit bye_module(void)
{
printk(KERN_INFO "Goodbye\n");
}
module_init(hello_module);
module_exit(bye_module);
Trong đoạn mã trên, chức năng của __init được sử dụng trong hàm hello_module là gì?
Định nghĩa phiên bản của module
Chỉ định rằng hàm sẽ chỉ được sử dụng khi khởi tạo module
Chỉ định rằng hàm sẽ chỉ được sử dụng khi gỡ bỏ module
Tự động gọi hàm khi module gặp lỗi
Trong đoạn mã trên, nếu muốn thay đổi thông báo từ "Hello" thành "Hello Linux", cần chỉnh sửa dòng nào?
MODULE_LICENSE("GPL");
printk(KERN_INFO "Hello\n");
module_init(hello_module);
MODULE_AUTHOR("KTMT");
int tong=0;
int __init hello_module(void)
{
int a=10;
int b=20;
tong=a+b;
......
return 0;
}
Điền vào chỗ trống câu lệnh đúng để in ra tổng của hai số a và b trong kernel module.
printk(KERN_WARNING "Tong: %d + %d = %d\n",a,b,tong);
printk(KERN_INFO "Tong: %d + %d = %d\n",a,b,tong);/
printk(KERN_DEBUG "Tong: %d + %d = %d\n",a,b,tong);
printf("Tong: %d + %d = %d\n",a,b,tong);
Đoạn code nào dưới đây của chương trình kernel module thực hiện khi tháo driver khỏi hệ thống, nó sẽ thực hiện tính tổng liên tiếp các số từ 1 đến 10 và in kết quả ra log của hệ thống?
int __init hello_module(void)
{
int sum = 0;
int i;
for (i = 1; i <= 10; i++) {
sum += i;
}
printk(KERN_INFO "Tong cac so tu 1 den 10 la: %d\n", sum);
}
void __exit bye_module(void)
{
int sum = 0;
int i;
for (i = 1; i <= 10; i++) {
sum += i;
}
printk(KERN_INFO "Tong cac so tu 1 den 10 la: %d\n", sum);
}
void tinhtong() {
int sum = 0;
int i;
for(i = 1; i <= 10; i++) {
sum += i;
}
printk(KERN_INFO "Tong cac so tu 1 den 10 la: %d\n");
}
int __init hello_module(void)
{
printk(KERN_INFO "Hello\n");
return 0;
}
void __exit bye_module(void)
{
printk(KERN_INFO "goodbyr\n");
}
void __exit bye_module(void)
{
int sum = 0;
int i;
for(i = 1; i <= 10; i++) {
sum += i;
}
printf("Tong cac so tu 1 den 10 la: %d\n");
}
Cấu trúc Makefile nào sau đây là đúng để biên dịch một kernel module có tên hel_sua.o và xóa các tệp biên dịch trước đó?
obj-m += hel_sua.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
rm -rf $(PWD)/hello.o
obj-m += hel_sua.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
make module
clean:
rm -rf /lib/modules/$(shell uname -r)/build
obj-m += hel_sua.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make clean
obj-m += hel_sua.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
Khi một module kernel được nạp vào kernel, hàm nào trong module đó sẽ được gọi đầu tiên?
printk
init
dmesg
exit
Hàm printk() trong kernel được sử dụng để làm gì?
Nạp một module vào kernel
Ghi dữ liệu vào file
In ra thông báo hoặc lỗi trong kernel log
Đọc dữ liệu từ kernel
Khi chạy trong user mode, một ứng dụng không thể trực tiếp truy cập vào:
Bộ nhớ của hệ thống
CPU
Tất cả các vùng bộ nhớ
Bộ nhớ của kernel
Sau khi sử dụng lệnh $ make để biên dịch một kernel module, kết quả của lệnh sẽ là gì?
Kiểm tra thông tin cấu hình của module.
Tạo ra tệp .ko để có thể nạp vào kernel.
Tạo ra một thư mục chứa các file log hệ thống.
Tạo ra một file thực thi trong user space.
Khi thực hiện lệnh $ insmod hello.ko để nạp một kernel module vào hệ thống, lệnh này yêu cầu quyền nào?
Quyền biên dịch
Quyền kiểm tra thông báo hệ thống
Quyền root hoặc quyền quản trị viên
Quyền của người dùng bình thường
Đoạn mã nào sau đây được viết đúng cho một kernel module trong Linux?
#include
#include
#include
#include
Cho tệp kernel_module.c chứa mã nguồn chương trình C như sau:
#include <linux/module.h>
#include <linux/kernel.h>
MODULE_AUTHOR("KTMT");
MODULE_LICENSE("GPL");
MODULE_VERSION("0.2");
int __init hello_module(void)
{
printk(KERN_INFO "Hello world\n");
return 0;
}
void __exit bye_module(void)
{
printk(KERN_INFO "Goodbye\n");
}
module_init(hello_module);
module_exit(bye_module);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("KTMT");
MODULE_DESCRIPTION("DRIVER");
Trong đoạn mã trên, lệnh nào được dùng để khai ký hàm hello_module làm hàm khởi tạo module khi nạp vào kernel?
module_init(hello_module);
init_module();
module_exit(bye_module);
start_module(hello_module);
Kernel space và user space khác nhau như thế nào?
Kernel space là vùng bộ nhớ dành riêng cho kernel và các phần mềm hệ thống, còn user space là vùng bộ nhớ dành cho các ứng dụng người dùng.
Không có sự khác biệt giữa chúng.
Kernel space chỉ dùng cho driver, còn user space chỉ dùng cho ứng dụng.
Kernel space dành cho các chương trình của người dùng, còn user space dành cho hệ thống.
Trong hệ điều hành Linux thì kernel module là gì?
Một tệp cấu hình của kernel được sử dụng để thay đổi các tham số hệ thống
Một đoạn mã được biên dịch thành tệp .exe và chạy trong không gian người dùng
Một chương trình độc lập chạy trên hệ điều hành mà không cần tương tác với kernel
Một đoạn mã hoặc chương trình được biên dịch thành tệp .ko và có thể nạp vào kernel tại th
Cho tệp kernel_module.c chứa mã nguồn chương trình C như sau:
#include <linux/module.h>
#include <linux/kernel.h>
MODULE_AUTHOR("KTMT");
MODULE_LICENSE("GPL");
MODULE_VERSION("0.2");
int __init hello_module(void)
{
printk(KERN_INFO "Hello world\n");
return 0;
}
void __exit bye_module(void)
{
printk(KERN_INFO "Goodbye\n");
}
module_init(hello_module);
module_exit(bye_module);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("KTMT");
MODULE_DESCRIPTION("DRIVER");
Trong đoạn mã trên, dòng MODULE_LICENSE("GPL"); có ý nghĩa gì?
Đảm bảo rằng module tuân theo giấy phép mã nguồn mở của GNU GPL
Định nghĩa mô tả module
Cấp phép sử dụng module cho người dùng thông thường
Xác định phiên bản của module
Cho tệp kernel_module.c chứa mã nguồn chương trình C như sau:
#include <linux/module.h>
#include <linux/kernel.h>
MODULE_AUTHOR("KTMT");
MODULE_LICENSE("GPL");
MODULE_VERSION("0.2");
int __init hello_module(void)
{
printk(KERN_INFO "Hello world\n");
return 0;
}
void __exit bye_module(void)
{
printk(KERN_INFO "Goodbye\n");
}
module_init(hello_module);
module_exit(bye_module);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("KTMT");
MODULE_DESCRIPTION("DRIVER");
Trong đoạn mã trên, dòng nào đảm bảo rằng module chỉ được gỡ khỏi kernel khi hàm bye_module được gọi?
module_init(hello_module);
MODULE_DESCRIPTION("DRIVER");
module_exit(bye_module);
MODULE_LICENSE("GPL");
Khi tháo module kernel, hàm nào sẽ được gọi?
init
dmesg
printk
exit
Xem xét đoạn mã sau.
int tong=0;
int __init hello_module(void)
{
int a=10;
int b=20;
tong = a + b;
return 0;
}
void __exit bye_module(void)
{
printk(KERN_INFO "Tong= %d\n", tong);
}
Lỗi gì có thể xảy ra nếu bye_module cố gắng truy cập biến cục bộ trong hello_module?
Lỗi biên dịch do sử dụng biến cục bộ tong trong bye_module.
Lỗi runtime do không thể truy cập biến cục bộ tổng.
Không có lỗi, chương trình sẽ hoạt động bình thường.
Lỗi logic do không tính tổng trong bye_module.
