1. Trang chủ
  2. » Công Nghệ Thông Tin

Chương 13: Lập trình Linux

33 763 5
Tài liệu đã được kiểm tra trùng lặp

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Tiêu đề Chương 13: Lập trình Linux
Trường học Đại Học Bách Khoa Hà Nội
Chuyên ngành Lập trình Linux
Thể loại Giáo trình
Năm xuất bản 2023
Thành phố Hà Nội
Định dạng
Số trang 33
Dung lượng 120 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

System call Parameters Trên kiến trúc i386 , system calls bị giới hạn đến 5 tham số không kể đến số hiệu system call bởi vì việc hạn chế số lượng thanh ghi có thể check kiểm tra để tìm

Trang 1

Linux Programing

Trang 3

 Nếu có các calls xuất hiện mà chúng chưa

có trong libc, ta có thể gọi syscall().

Trang 4

System calls

 Ví dụ, ta có thể đóng file dùng syscall() như sau (không khuyến khích):

 #include <syscall.h>

 extern int syscall(int, );

 int my_close(int filedescriptor)

 {

 return syscall(SYS_close, filedescriptor);

 }

Trang 5

System call Parameters

 Trên kiến trúc i386 , system calls bị giới hạn đến

5 tham số không kể đến số hiệu system call bởi

vì việc hạn chế số lượng thanh ghi

có thể check kiểm tra <asm/unistd.h> để tìm các syscall macros để xem phần cứng của bạn có thể

hỗ trợ đến bao nhiêu tham số

cho syscall(), nhưng nó không được khuyến khích khi đã có những macro được phát triển thành các hàm đầy đủ tồn tại trong thư viện lập trình

Trang 6

System call Parameters (tt)

 Do đó chỉ có những tay chuyên nghiệp mới nên chơi với các syscall macros Ví dụ đây là một

hàm close() có dùng syscall macro

#include <linux/unistd.h>

_syscall1(int, close, int,

filedescriptor);

 syscall1 macro mở rộng hàm close() Do đó ta

có close() xuất hiện 2 lần: một trong libc và một trong chương trình của ta Giá trị trả về của

syscall() hay syscall macro là -1 nếu system call thất bại và 0 hoặc lớn hơn nếu thành công

Trang 7

System Call không có trong Linux

 Các system call sau là tồn tại trên BSD và SYS V nhưng không tồn tại trên Linux:

 audit(), auditon(), auditsvc(), fchroot(),

getauid(), getdents(), getmsg(), mincore(),

poll(),putmsg(), setaudit(), setauid()

Trang 8

The “swiss army knife” ioctl

screwdriver, screwdriver, corkscrew, scissors, metal saw, wood saw, can

metal file, wire bender, large blade, small blade, cap lifter, wire stripper,

multi-purpose hook, chisel, wire cutters, pin, nail cleaner,

multipurpose pliers, clef 6 pans 5mm pour connecteurs

D-SUB,embout Pozidrive 0, embout Pozidrive 1, embout

tournevis, embout Phillips 2, embout Hex (inbus), embout

Torx 8, embout Torx 10, embout Torx 15, long ballpoint

http://www.swiss-knife.com/asp/detail.asp?lan=EN&code=1.7775.T&shop=SK

Trang 9

The “swiss army knife” ioctl

 ioctl viết tắt cho input/output control và

nó được dùng để thao tác đến các

character device thông qua filedescriptor

 Format của ioctl là

 ioctl(unsigned int fd, unsigned int request,

unsigned long argument)

 Giá trị trả về là -1 nếu có lỗi và =0 nếu

request thành công (tương tự như các system call khác)

Trang 10

ioctl (tt)

 Kernel phân biệt các file đặc biệt và file thông thường File đặc biệt là những file nằm trong /dev và /proc Chúng khác với các file thông

thường là chúng dấu các giao diện với driver và không phải là một file thật sự chứa dữ liệu text hay binary Đây là triết lý của UNIX và cho phép dùng các thao tác read/write thông thường trên tất cả các file

 Bạn sẽ cần dùng ioctl nhiều khi thao tác với các file đặc biệt hơn là với các file thường Nhưng bạn cũng có thể dùng ioctl trên các file thường !

Trang 11

InterProcess Communications-IPC

 Cơ chế IPC trong Linux cung cấp một phương pháp cho nhiều tiến trình giao tiếp với nhau Có nhiều

phương pháp IPC cho Linux C programmers áp dụng:

 Half-duplex UNIX pipes

 FIFOs (named pipes)

 SYSV style message queues

 SYSV style semaphore sets

 SYSV style shared memory segments

 Networking sockets (Berkeley style, không đề cập )

 Full-duplex pipes (STREAMS pipes,, không đề cập )

 Các phương pháp này, khi được dùng một cách hiệu quả, sẽ mang lại một framework vững chắc cho

client/server development trên bất kỳ một hệ UNIX

nào (bao gồm cả Linux).

Trang 12

Half-duplex UNIX Pipes

Khái niệm căn bản: pipe là một phương

pháp của việc kết nối standard output của một tiến trình process vào một standard input của tiến trình khác Pipes là một công cụ IPC cổ

nhất, nó có từ giai đoạn phôi thai nhất của HĐH UNIX Chúng cung cấp một của việc giao tiêế 1 chiều (thuật ngữ half-duplex) giữa các process Tính năng này được dùng rộng rãi, thậm chí

trong shell của Unix

ls | sort | lp

Trang 13

Half-duplex UNIX Pipes

Tạo pipes trong C

 Để tạo một pipe đơn giản trong C, ta cần

dùng pipe() system call Nó cần 1 tham số, đó

là một array có 2 số integer và nếu thành

công, array sẽ chứa 2 file descriptors mới để được dùng cho pipeline Sau khi tạo pipe,

process thường sinh ra 1 tiến trình mới (lưu ý rằng, tiến trình con thừa kế mô tả file đã mở)

Trang 14

T ạo pipes trong C

 SYSTEM CALL: pipe();

 PROTOTYPE: int pipe( int fd[2] );

 RETURNS: 0 on success

 -1 on error: errno = EMFILE (no free

descriptors)

 EMFILE (system file table is full)

 EFAULT (fd array is not valid)

 NOTES: fd[0] is set up for reading, fd[1] is set

up for writing

Trang 15

T ạo pipes trong C

 Giá trị integer đầu tiên trong array được thiết lập

và mở ra cho việc đọc, trong khi số integer thứ hai được thiết lập và mở ra cho việc ghi

 Nói một cách hình tượng, output của fd1 trở thành input cho fd0 Một lần nữa, tất cả data di chuyển thông qua pipe đi vào kernel.

#include <stdio.h>

#include <unistd.h>

#include <sys/types.h>

main() {

int fd[2];

pipe(fd);

… }

Trang 16

of pipe */

close(fd[1]);

/* Read in a string from the pipe */

nbytes = read(fd[0], readbuffer, sizeof(readbuffer));

printf("Received string: %s", readbuffer); }

return(0);

}

Trang 17

Các lưu ý trong half-duplex pipes

 pipes hai chiều có thể được tạo ra bằng cách mở hai pipes, và được gán lại file descriptors một cách

thích hợp trong tiến trình con

 Lời gọi pipe() phải được thực hiện trước khi gọi

fork(), nếu không thì descriptors sẽ không được thừa

kế bởi tiến trình con !

 Với half-duplex pipes, bất kỳ tiến trình kết nối nào

phải được chia sẽ cùng một tổ tiên Khi pipe cư trú bên trong sự kềm hãm của kernel, bất cứ một tiến trình nào mà không cùng tổ tiên của pipe thì không

có cách nào tìm đến được nó

Trang 18

Named Pipes (FIFOs)

như pipe thông thường, nhưng có một số khác biệt đáng chú ý:

 Named pipes tồn tại như là một device special file trong file system

 Các tiến trình khác tổ tiên có thể chia sẽ data thông qua một named pipe

 Khi tất cả I/O được hoàn tất bởi các tiến trình chia sẻ, named pipe còn lưu lại trong file

system để dùng sau

Trang 19

Tạo FIFO

 Có nhiều cách để tạo một named pipe Hai cách đầu tiên là tạo trực tiếp từ shell.

 mknod MYFIFO p

 mkfifo a=rw MYFIFO

 FIFO files có thể được xác định trong

physical file system bởi ký tự “p” ở đầu tiên:

[root@pascal root]# ls -l MYFIFO

prw-r r 1 root root 0 Aug 23 23:35 MYFIFO

[root@pascal root]#

Trang 20

Tạo FIFO trong C

LIBRARY FUNCTION: mknod();

PROTOTYPE: int mknod( char *pathname, mode_t mode, dev_t dev);

RETURNS: 0 on success,

-1 on error:errno=EFAULT (pathname invalid)

EACCES (permission denied) ENAMETOOLONG (pathname too long)

ENOENT (invalid pathname) ENOTDIR (invalid pathname)

Trang 21

 Muốn biến rõ hơn về mknod thì hãy dùng lệnh

man,nhưng xét ví dụ đơn giản sau trong C:

 mknod("/tmp/MYFIFO", S_IFIFO|0666, 0);

 Ở đây, file “/tmp/MYFIFO” được tạo ra như là một FIFO file Quyền của file là “0666”, mặc dù chúng

bị ảnh hưởng bởi umask setting như sau:

 Một mẹo nhỏ dùng umask() system call để tạm thời

vô hiệu giá trị umask :

Trang 22

filesystem Trong ví dụ, chúng ta sẽ xem như pipe là một stream, mở nó ra với fopen() và

đóng với fclose()

Trang 25

 #include <stdio.h>

 #include <stdlib.h>

 #define FIFO_FILE "MYFIFO"

 int main(int argc, char *argv[])

Trang 27

Blocking Actions on a FIFO

 Thông thường, blocking xảy ra trên FIFO Nói cách khác nếu FIFO được mở để đọc, process sẽ ”block” cho đến khi một vài

process khác mở nó ra để viết vào Nếu hành vi này là không mong muốn thì một

cờ O_NONBLOCK có thể được dùng trong open() call để disable default blocking

action.

Trang 28

Infamous SIGPIPE Signal

 Một chú ý cuối cùng, pipes phải có một

reader và một writer Nếu một process cố gắng ghi vào một pipe mà không có

reader, nó sẽ được gửi đến 1 tín hiệu

SIGPIPE từ kernel Điều này là bắt buộc

khi có nhiều hơn hai tiến trình thao tác với một pipeline.

Trang 30

Introduction

Trang 31

Socket

Trang 32

*)&address, len);

if(result == -1) { perror("oops: client1 problem"); exit(1);

} write(sockfd, &ch, 1);

Trang 33

int server_sockfd, client_sockfd;

int server_len, client_len;

*)&server_address, server_len); listen(server_sockfd, 5);

while(1) { char ch;

printf("server waiting\n"); client_sockfd =

accept(server_sockfd, (struct sockaddr

*)&client_address, &client_len); read(client_sockfd, &ch, 1); ch++;

write(client_sockfd, &ch, 1); close(client_sockfd);

Ngày đăng: 08/05/2014, 13:49

TỪ KHÓA LIÊN QUAN

w