diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..4e90c75 --- /dev/null +++ b/.clang-format @@ -0,0 +1,16 @@ +BasedOnStyle: LLVM +IndentWidth: 8 +TabWidth: 8 +UseTab: Always +BreakBeforeBraces: Linux +AllowShortIfStatementsOnASingleLine: false +AllowShortLoopsOnASingleLine: false +AllowShortFunctionsOnASingleLine: InlineOnly +ColumnLimit: 80 +AlignConsecutiveDeclarations: false +AlignConsecutiveAssignments: false +AlignEscapedNewlines: Left +AlignOperands: false +IndentCaseLabels: false +SpaceBeforeParens: ControlStatements + diff --git a/README.md b/README.md index f02b951..8167389 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,7 @@ Welcome! This is a collection of chapter summaries from the book **Linux System - [Chapter 3 – Buffered I/O](chp3/README.md) - [Chapter 4 – Advanced File I/O](chp4/README.md) - [Chapter 5 - Process Management](chp5/README.md) +- [Chapter 6 - Advanced Process Management](chp6/README.md) - [Exercises](exercises/README.md) > Each file contains an English summary of the chapter's key concepts. diff --git a/chp1/syscalls/example1.c b/chp1/syscalls/example1.c index 26aa5c2..0554f19 100644 --- a/chp1/syscalls/example1.c +++ b/chp1/syscalls/example1.c @@ -2,8 +2,9 @@ #include #include -int main(void) { - int fd = open("test.txt", O_CREAT | O_RDWR); - // close(fd); - return EXIT_SUCCESS; +int main(void) +{ + int fd = open("test.txt", O_CREAT | O_RDWR); + // close(fd); + return EXIT_SUCCESS; } diff --git a/chp2/fopenflags.c b/chp2/fopenflags.c index bae1670..5beb87e 100644 --- a/chp2/fopenflags.c +++ b/chp2/fopenflags.c @@ -1,7 +1,7 @@ -#include -#include -#include #include +#include +#include +#include int main(void) { @@ -20,7 +20,7 @@ int main(void) if (fd == -1) perror("Third open"); close(fd); - + fd = open("test.txt", O_CREAT); if (fd == -1) perror("Fourth open"); diff --git a/chp2/fopenmode.c b/chp2/fopenmode.c index 4ab2c14..41aa3e7 100644 --- a/chp2/fopenmode.c +++ b/chp2/fopenmode.c @@ -1,12 +1,13 @@ -#include -#include -#include #include +#include +#include +#include int main(void) { int fd; - fd = open("test.txt", O_CREAT | O_EXCL, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH); + fd = open("test.txt", O_CREAT | O_EXCL, + S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH); if (fd == -1) perror("open"); close(fd); diff --git a/chp2/fpread.c b/chp2/fpread.c index 66621dd..5714a44 100644 --- a/chp2/fpread.c +++ b/chp2/fpread.c @@ -6,51 +6,56 @@ #define _XOPEN_SOURCE 500 #include -int main(void) { - printf("Try to open file read.txt\n"); - int fd = open("read.txt", O_RDONLY); - if (fd == -1) { - perror("Failed to open read.txt"); - return -1; - } - printf("Open file success\n"); +int main(void) +{ + printf("Try to open file read.txt\n"); + int fd = open("read.txt", O_RDONLY); + if (fd == -1) { + perror("Failed to open read.txt"); + return -1; + } + printf("Open file success\n"); - int len; - // move file's cursor at the end of file and return bytes - if ((len = lseek(fd, 0, SEEK_END)) == -1) { - perror("Failed to move cursor at end of read.txt file"); - return -1; - } + int len; + // move file's cursor at the end of file and return bytes + if ((len = lseek(fd, 0, SEEK_END)) == -1) { + perror("Failed to move cursor at end of read.txt file"); + return -1; + } - // cannot rewind cursor at the start file because pread use "bytes_read_total" for position + // cannot rewind cursor at the start file because pread use + // "bytes_read_total" for position - printf("File size of %d bytes\n", len); + printf("File size of %d bytes\n", len); - printf("Reading file read.txt\n"); - char buf[len + 1]; - memset(buf, 0, sizeof(buf)); + printf("Reading file read.txt\n"); + char buf[len + 1]; + memset(buf, 0, sizeof(buf)); - size_t bytes_read_total = 0; - ssize_t ret; - while (bytes_read_total < len && (ret = pread(fd, buf, len - bytes_read_total, bytes_read_total)) != -1) { - if (ret == -1) { - if (errno == EINTR) continue; - perror("Failed to read read.txt"); - break; - } - bytes_read_total += ret; - } + size_t bytes_read_total = 0; + ssize_t ret; + while (bytes_read_total < len && + (ret = pread(fd, buf, len - bytes_read_total, + bytes_read_total)) != -1) { + if (ret == -1) { + if (errno == EINTR) + continue; + perror("Failed to read read.txt"); + break; + } + bytes_read_total += ret; + } - buf[bytes_read_total] = '\0'; + buf[bytes_read_total] = '\0'; - printf("File text is:\n\"%s\"\n", buf); + printf("File text is:\n\"%s\"\n", buf); - printf("Close file read.txt\n"); - - if (close(fd) == -1) { - perror("Failed to close read.txt"); - return -1; - } + printf("Close file read.txt\n"); - return 0; + if (close(fd) == -1) { + perror("Failed to close read.txt"); + return -1; + } + + return 0; } diff --git a/chp2/fread.c b/chp2/fread.c index e15d2ba..36d3eca 100644 --- a/chp2/fread.c +++ b/chp2/fread.c @@ -5,51 +5,55 @@ #include #include -int main(void) { - printf("Try to open file read.txt\n"); - int fd = open("read.txt", O_RDONLY); - if (fd == -1) { - perror("Failed to open read.txt"); - return -1; - } - printf("Open file success\n"); +int main(void) +{ + printf("Try to open file read.txt\n"); + int fd = open("read.txt", O_RDONLY); + if (fd == -1) { + perror("Failed to open read.txt"); + return -1; + } + printf("Open file success\n"); - int len; - if ((len = lseek(fd, 0, SEEK_END)) == -1) { - perror("Failed to move cursor at end of read.txt file"); - return -1; - } - printf("File size of %d bytes\n", len); - if (lseek(fd, 0, SEEK_SET) == -1) { - perror("Failed to move cursor at start of read.txt file"); - return -1; - } + int len; + if ((len = lseek(fd, 0, SEEK_END)) == -1) { + perror("Failed to move cursor at end of read.txt file"); + return -1; + } + printf("File size of %d bytes\n", len); + if (lseek(fd, 0, SEEK_SET) == -1) { + perror("Failed to move cursor at start of read.txt file"); + return -1; + } - printf("Reading file read.txt\n"); - char buf[len + 1]; - memset(buf, 0, sizeof(buf)); + printf("Reading file read.txt\n"); + char buf[len + 1]; + memset(buf, 0, sizeof(buf)); - size_t bytes_read_total = 0; - ssize_t ret; - while (bytes_read_total < len && (ret = read(fd, buf + bytes_read_total, len - bytes_read_total)) != 0) { - if (ret == -1) { - if (errno == EINTR) continue; - perror("Failed to read read.txt"); - break; - } - bytes_read_total += ret; - } + size_t bytes_read_total = 0; + ssize_t ret; + while (bytes_read_total < len && + (ret = read(fd, buf + bytes_read_total, + len - bytes_read_total)) != 0) { + if (ret == -1) { + if (errno == EINTR) + continue; + perror("Failed to read read.txt"); + break; + } + bytes_read_total += ret; + } - buf[bytes_read_total] = '\0'; + buf[bytes_read_total] = '\0'; - printf("File text is:\n\"%s\"\n", buf); + printf("File text is:\n\"%s\"\n", buf); - printf("Close file read.txt\n"); - - if (close(fd) == -1) { - perror("Failed to close read.txt"); - return -1; - } + printf("Close file read.txt\n"); - return 0; + if (close(fd) == -1) { + perror("Failed to close read.txt"); + return -1; + } + + return 0; } diff --git a/chp2/ftruncate.c b/chp2/ftruncate.c index b80f90e..47ba2d6 100644 --- a/chp2/ftruncate.c +++ b/chp2/ftruncate.c @@ -1,7 +1,8 @@ -#include #include +#include -int main(void) { +int main(void) +{ int ret; ret = truncate("./pirate.txt", 45); diff --git a/chp2/poll.c b/chp2/poll.c index 2c8ebfa..c4338d7 100644 --- a/chp2/poll.c +++ b/chp2/poll.c @@ -1,10 +1,11 @@ +#include #include #include -#include -#define TIMEOUT 5 /* poll timeout, in seconds */ +#define TIMEOUT 5 /* poll timeout, in seconds */ -int main(void) { +int main(void) +{ struct pollfd fds[2]; int ret; @@ -30,7 +31,7 @@ int main(void) { if (fds[0].revents & POLLIN) printf("stdin is readable\n"); - + if (fds[1].revents & POLLOUT) printf("stdout is writable\n"); diff --git a/chp2/select.c b/chp2/select.c index 0a5c021..ed685f0 100644 --- a/chp2/select.c +++ b/chp2/select.c @@ -6,7 +6,8 @@ #define TIMEOUT 5 #define BUF_LEN 1024 -int main(void) { +int main(void) +{ struct timeval tv; fd_set readfds; int ret; @@ -14,19 +15,13 @@ int main(void) { /* Wait on stdin for intput. */ FD_ZERO(&readfds); FD_SET(STDIN_FILENO, &readfds); - + /* Wait up to file seconds */ tv.tv_sec = TIMEOUT; tv.tv_usec = 0; /* All right, now block! */ - ret = select( - STDIN_FILENO + 1, - &readfds, - NULL, - NULL, - &tv - ); + ret = select(STDIN_FILENO + 1, &readfds, NULL, NULL, &tv); if (ret == -1) { perror("select"); return 1; @@ -42,7 +37,7 @@ int main(void) { * nonzero, but we will humor ourselves.) */ if (FD_ISSET(STDIN_FILENO, &readfds)) { - char buf[BUF_LEN+1]; + char buf[BUF_LEN + 1]; int len; /* guaranteed to not block */ @@ -56,7 +51,7 @@ int main(void) { buf[len] = '\0'; printf("read: %s\n", buf); } - + return 0; } diff --git a/chp2/select_regular_files.c b/chp2/select_regular_files.c index 42a0039..01df9b6 100644 --- a/chp2/select_regular_files.c +++ b/chp2/select_regular_files.c @@ -1,11 +1,11 @@ +#include +#include #include #include -#include -#include -#include #include -#include #include +#include +#include #define FILE_NUMBER 3 #define FILENAME_MAX_LEN 10 @@ -15,7 +15,8 @@ int create_tmp_file(char *filename); void cleanup(char *filenames[]); -int main(void) { +int main(void) +{ int exit_code = 0; char *filename_template = "test%d.txt"; char *filenames[FILE_NUMBER] = {NULL}; @@ -23,48 +24,47 @@ int main(void) { // Create a bunch of number ephemeral files for (int i = 0; i < FILE_NUMBER; i++) { - char *filename = (char *)malloc(FILENAME_MAX_LEN*sizeof(char)); + char *filename = + (char *)malloc(FILENAME_MAX_LEN * sizeof(char)); if (!filename) { perror("malloc failed"); exit_code = -1; goto exit; } - snprintf(filename, FILENAME_MAX_LEN, filename_template, i+1); + snprintf(filename, FILENAME_MAX_LEN, filename_template, i + 1); filenames[i] = filename; printf("Opening file %s...\n", filename); fds[i] = create_tmp_file(filename); if (fds[i] == -1) { - fprintf(stderr, "Error to open file %s: %s\n", filename, strerror(errno)); + fprintf(stderr, "Error to open file %s: %s\n", filename, + strerror(errno)); exit_code = -1; goto exit; } - printf("Open file %s with file descriptor %d\n", filename, fds[i]); + printf("Open file %s with file descriptor %d\n", filename, + fds[i]); // write something in the files dprintf(fds[i], "Hello I am %s\n", filename); } - + fd_set readfds; FD_ZERO(&readfds); for (int i = 0; i < FILE_NUMBER; i++) { FD_SET(fds[i], &readfds); } - - struct timeval *timeout = (struct timeval *)malloc(sizeof(struct timeval)); + + struct timeval *timeout = + (struct timeval *)malloc(sizeof(struct timeval)); timeout->tv_sec = TIMEOUT; timeout->tv_usec = 0; - - /* This function do not work with regular files because for the operating system, - * a regular file is ready always. - * This example is wrong the best way to use select() is with socket, pipe or other channel types. + + /* This function do not work with regular files because for the + * operating system, a regular file is ready always. This example is + * wrong the best way to use select() is with socket, pipe or other + * channel types. */ - int ret = select( - FILE_NUMBER + 1, - &readfds, - NULL, - NULL, - timeout - ); + int ret = select(FILE_NUMBER + 1, &readfds, NULL, NULL, timeout); if (ret == -1) { fprintf(stderr, "Error to select: %s\n", strerror(errno)); @@ -79,10 +79,11 @@ int main(void) { for (int i = 0; i < FILE_NUMBER; i++) { int fd = fds[i]; if (FD_ISSET(fd, &readfds)) { - char buf[BUF_LEN+1]; + char buf[BUF_LEN + 1]; int len = read(fd, buf, BUF_LEN); if (len == -1) { - fprintf(stderr, "Error reading file %s: %s\n", filenames[i], strerror(errno)); + fprintf(stderr, "Error reading file %s: %s\n", + filenames[i], strerror(errno)); exit_code = 1; goto exit; } @@ -98,8 +99,9 @@ exit: for (int i = 0; i < FILE_NUMBER; i++) { int fd = fds[i]; printf("Close file with file descriptor %d\n", fd); - if (close(fd) == -1) { - fprintf(stderr, "Error to close file %d: %s\n", fd, strerror(errno)); + if (close(fd) == -1) { + fprintf(stderr, "Error to close file %d: %s\n", fd, + strerror(errno)); } } @@ -108,11 +110,12 @@ exit: printf("Cleanup files\n"); cleanup(filenames); - + return exit_code; } -int create_tmp_file(char *filename) { +int create_tmp_file(char *filename) +{ int fd = open(filename, O_CREAT | O_EXCL | O_RDWR, 0644); if (fd == -1) { return -1; @@ -120,11 +123,13 @@ int create_tmp_file(char *filename) { return fd; } -void cleanup(char *filenames[]) { +void cleanup(char *filenames[]) +{ for (int j = 0; j < FILE_NUMBER; j++) { if (filenames[j] != NULL) { - if (remove(filenames[j]) == -1) - fprintf(stderr, "Failed to remove %s: %s\n", filenames[j], strerror(errno)); + if (remove(filenames[j]) == -1) + fprintf(stderr, "Failed to remove %s: %s\n", + filenames[j], strerror(errno)); free(filenames[j]); filenames[j] = NULL; } diff --git a/chp3/binarydata.c b/chp3/binarydata.c index cae1965..ce68460 100644 --- a/chp3/binarydata.c +++ b/chp3/binarydata.c @@ -1,40 +1,42 @@ #include -int main(void) { - FILE *in, *out; - struct pirate { - char name[100]; /* real name */ - unsigned long booty; /* in pounds sterling */ - unsigned int beard_len; /* in inches */ - } p, blackbeard = {"Edward Teach", 950, 48}; +int main(void) +{ + FILE *in, *out; + struct pirate { + char name[100]; /* real name */ + unsigned long booty; /* in pounds sterling */ + unsigned int beard_len; /* in inches */ + } p, blackbeard = {"Edward Teach", 950, 48}; - out = fopen("data", "w"); - if (!out) { - perror("fopen"); - return 1; - } - if (!fwrite(&blackbeard, sizeof(struct pirate), 1, out)) { - perror("fwrite"); - return 1; - } - if (fclose(out)) { - perror("fclose"); - return 1; - } + out = fopen("data", "w"); + if (!out) { + perror("fopen"); + return 1; + } + if (!fwrite(&blackbeard, sizeof(struct pirate), 1, out)) { + perror("fwrite"); + return 1; + } + if (fclose(out)) { + perror("fclose"); + return 1; + } - in = fopen("data", "r"); - if (!in) { - perror("fopen"); - return 1; - } - if (!fread(&p, sizeof(struct pirate), 1, in)) { - perror("fread"); - return 1; - } - if (fclose(in)) { - perror("fclose"); - return 1; - } - printf("name=\"%s\" booty=%lu beard_len=%u\n", p.name, p.booty, p.beard_len); - return 0; + in = fopen("data", "r"); + if (!in) { + perror("fopen"); + return 1; + } + if (!fread(&p, sizeof(struct pirate), 1, in)) { + perror("fread"); + return 1; + } + if (fclose(in)) { + perror("fclose"); + return 1; + } + printf("name=\"%s\" booty=%lu beard_len=%u\n", p.name, p.booty, + p.beard_len); + return 0; } diff --git a/chp3/input.c b/chp3/input.c index 3e72a56..8ea91d9 100644 --- a/chp3/input.c +++ b/chp3/input.c @@ -1,7 +1,8 @@ -#include #include +#include -int main(void) { - printf("Limit buffer size is %u bytes.\n", LINE_MAX); - printf("Buffer size is %u bytes.\n", BUFSIZ); +int main(void) +{ + printf("Limit buffer size is %u bytes.\n", LINE_MAX); + printf("Buffer size is %u bytes.\n", BUFSIZ); } diff --git a/chp4/blocks.c b/chp4/blocks.c index 4c3d3e4..af4e959 100644 --- a/chp4/blocks.c +++ b/chp4/blocks.c @@ -1,10 +1,10 @@ +#include +#include #include #include -#include -#include -#include #include -#include +#include +#include /* get_block - for the file associated with the given fd, returns * the physical block mapping to logical_block @@ -22,66 +22,71 @@ int get_nr_blocks(int fd); */ void print_blocks(int fd); -int main(int argc, char *argv[]) { - if (argc < 2) { - fprintf(stderr, "usage: %s \n", argv[0]); - return 1; - } +int main(int argc, char *argv[]) +{ + if (argc < 2) { + fprintf(stderr, "usage: %s \n", argv[0]); + return 1; + } - int fd = open(argv[1], O_RDONLY); - if (fd < 0) { - perror("open"); - return 1; - } + int fd = open(argv[1], O_RDONLY); + if (fd < 0) { + perror("open"); + return 1; + } - print_blocks(fd); - return 0; + print_blocks(fd); + return 0; } -int get_block(int fd, int logical_block) { - int ret = ioctl(fd, FIBMAP, &logical_block); - if (ret < 0) { - perror("ioctl"); - return -1; - } - return logical_block; +int get_block(int fd, int logical_block) +{ + int ret = ioctl(fd, FIBMAP, &logical_block); + if (ret < 0) { + perror("ioctl"); + return -1; + } + return logical_block; } -int get_nr_blocks(int fd) { - struct stat buf; - int ret = fstat(fd, &buf); - if (ret < 0) { - perror("fstat"); - return -1; - } - return buf.st_blocks; +int get_nr_blocks(int fd) +{ + struct stat buf; + int ret = fstat(fd, &buf); + if (ret < 0) { + perror("fstat"); + return -1; + } + return buf.st_blocks; } -void print_blocks(int fd) { - int nr_blocks = get_nr_blocks(fd); - if (nr_blocks < 0) { - fprintf(stderr, "get_nr_blocks failed!\n"); - return; - } +void print_blocks(int fd) +{ + int nr_blocks = get_nr_blocks(fd); + if (nr_blocks < 0) { + fprintf(stderr, "get_nr_blocks failed!\n"); + return; + } - if (nr_blocks == 0) { - printf("no allocated blocks\n"); - return; - } else if (nr_blocks == 1) { - printf("1 block\n"); - } else { - printf("%d blocks\n\n", nr_blocks); - } + if (nr_blocks == 0) { + printf("no allocated blocks\n"); + return; + } else if (nr_blocks == 1) { + printf("1 block\n"); + } else { + printf("%d blocks\n\n", nr_blocks); + } - for (int i = 0; i < nr_blocks; i++) { - int phys_block = get_block(fd, i); - if (phys_block < 0) { - fprintf(stderr, "get_block failed!\n"); - return; - } - if (!phys_block) continue; + for (int i = 0; i < nr_blocks; i++) { + int phys_block = get_block(fd, i); + if (phys_block < 0) { + fprintf(stderr, "get_block failed!\n"); + return; + } + if (!phys_block) + continue; - printf("(%u, %u) ", i, phys_block); - } - putchar('\n'); + printf("(%u, %u) ", i, phys_block); + } + putchar('\n'); } diff --git a/chp4/inode.c b/chp4/inode.c index 183e0dd..1ac89db 100644 --- a/chp4/inode.c +++ b/chp4/inode.c @@ -1,39 +1,41 @@ +#include #include #include -#include -#include #include +#include /* get_inode - returns the inode of the file associated * with the given file descriptor, or -1 on failure. */ int get_inode(int fd); -int main(int argc, char *argv[]) { - if (argc < 2) { - fprintf(stderr, "usage: %s \n", argv[0]); - return 1; - } +int main(int argc, char *argv[]) +{ + if (argc < 2) { + fprintf(stderr, "usage: %s \n", argv[0]); + return 1; + } - int fd = open(argv[1], O_RDONLY); - if (fd < 0) { - perror("open"); - return 1; - } + int fd = open(argv[1], O_RDONLY); + if (fd < 0) { + perror("open"); + return 1; + } - int inode = get_inode(fd); - printf("%d\n", inode); - - return 0; + int inode = get_inode(fd); + printf("%d\n", inode); + + return 0; } -int get_inode(int fd) { - struct stat buf; +int get_inode(int fd) +{ + struct stat buf; - int ret = fstat(fd, &buf); - if (ret < 0) { - perror("fstat"); - return -1; - } - return buf.st_ino; + int ret = fstat(fd, &buf); + if (ret < 0) { + perror("fstat"); + return -1; + } + return buf.st_ino; } diff --git a/chp4/mmap.c b/chp4/mmap.c index 11c9843..789c026 100644 --- a/chp4/mmap.c +++ b/chp4/mmap.c @@ -1,12 +1,13 @@ -#include -#include -#include #include -#include +#include #include +#include +#include +#include + +int main(int argc, char *argv[]) +{ -int main(int argc, char *argv[]) { - if (argc < 2) { fprintf(stderr, "usage: %s \n", argv[0]); return 1; diff --git a/chp4/readv.c b/chp4/readv.c index 7f9e195..8088559 100644 --- a/chp4/readv.c +++ b/chp4/readv.c @@ -1,41 +1,42 @@ -#include -#include -#include #include +#include +#include +#include #include #include -int main(void) { - char foo[48], bar[51], baz[49]; - int fd = open("buccaneer.txt", O_RDONLY); - if (fd == -1) { - perror("open"); - return 1; - } +int main(void) +{ + char foo[48], bar[51], baz[49]; + int fd = open("buccaneer.txt", O_RDONLY); + if (fd == -1) { + perror("open"); + return 1; + } - // setup our iovec structures - struct iovec iov[3]; - iov[0].iov_base = foo; - iov[0].iov_len = sizeof(foo); - iov[1].iov_base = bar; - iov[1].iov_len = sizeof(bar); - iov[2].iov_base = baz; - iov[2].iov_len = sizeof(baz); + // setup our iovec structures + struct iovec iov[3]; + iov[0].iov_base = foo; + iov[0].iov_len = sizeof(foo); + iov[1].iov_base = bar; + iov[1].iov_len = sizeof(bar); + iov[2].iov_base = baz; + iov[2].iov_len = sizeof(baz); - // read into the structures with a single call - int nr = readv(fd, iov, 3); - if (nr == -1) { - perror("readv"); - return 1; - } + // read into the structures with a single call + int nr = readv(fd, iov, 3); + if (nr == -1) { + perror("readv"); + return 1; + } - for (int i = 0; i < 3; i++) - printf("%d: %s", i, (char *)iov[i].iov_base); + for (int i = 0; i < 3; i++) + printf("%d: %s", i, (char *)iov[i].iov_base); - if (close(fd)) { - perror("close"); - return 1; - } + if (close(fd)) { + perror("close"); + return 1; + } - return 0; + return 0; } diff --git a/chp4/writev.c b/chp4/writev.c index 414364c..1d284aa 100644 --- a/chp4/writev.c +++ b/chp4/writev.c @@ -1,45 +1,44 @@ -#include -#include -#include #include +#include #include +#include +#include #include #include -int main(void) { - struct iovec iov[3]; +int main(void) +{ + struct iovec iov[3]; - char *buf[] = { - "The term buccaneer comes from the word boucan.\n", - "A boucan is a wooden frame used for cooking meet.\n", - "Buccaneer is the West Indies name for a pirate.\n" - }; + char *buf[] = {"The term buccaneer comes from the word boucan.\n", + "A boucan is a wooden frame used for cooking meet.\n", + "Buccaneer is the West Indies name for a pirate.\n"}; - int fd = open("buccaneer.txt", O_WRONLY | O_CREAT | O_TRUNC); - if (fd == -1) { - perror("open"); - return 1; - } + int fd = open("buccaneer.txt", O_WRONLY | O_CREAT | O_TRUNC); + if (fd == -1) { + perror("open"); + return 1; + } - // fill out three iovec structures - for (int i = 0; i < 3; i++) { - iov[i].iov_base = buf[i]; - iov[i].iov_len = strlen(buf[i]) + 1; - } + // fill out three iovec structures + for (int i = 0; i < 3; i++) { + iov[i].iov_base = buf[i]; + iov[i].iov_len = strlen(buf[i]) + 1; + } - // with a single call, write them all out - ssize_t nr = writev(fd, iov, 3); - if (nr == -1) { - perror("writev"); - return 1; - } + // with a single call, write them all out + ssize_t nr = writev(fd, iov, 3); + if (nr == -1) { + perror("writev"); + return 1; + } - printf("wrote %lu bytes\n", nr); + printf("wrote %lu bytes\n", nr); - if (close(fd)) { - perror("close"); - return 1; - } + if (close(fd)) { + perror("close"); + return 1; + } - return 0; + return 0; } diff --git a/chp5/atexit.c b/chp5/atexit.c index 2b064c2..9967300 100644 --- a/chp5/atexit.c +++ b/chp5/atexit.c @@ -1,15 +1,16 @@ #include #include -void out(void) { - printf("atexit() succeeded!\n"); +void out(void) +{ + printf("atexit() succeeded!\n"); } - -int main(void) { - if (atexit(out)) { - fprintf(stderr, "atexit() failed\n"); - return 1; - } - return 0; +int main(void) +{ + if (atexit(out)) { + fprintf(stderr, "atexit() failed\n"); + return 1; + } + return 0; } diff --git a/chp5/daemon.c b/chp5/daemon.c index 57df951..c697c5c 100644 --- a/chp5/daemon.c +++ b/chp5/daemon.c @@ -1,43 +1,46 @@ -#include -#include -#include -#include #include +#include +#include +#include +#include #include #define NR_OPEN 1048576 -int main(void) { - // create new process - pid_t pid = fork(); - if (pid == -1) { - return -1; - } else if (pid != 0) { - printf("Running daemon with pid %d\n", pid); - exit(EXIT_SUCCESS); - } +int main(void) +{ + // create new process + pid_t pid = fork(); + if (pid == -1) { + return -1; + } else if (pid != 0) { + printf("Running daemon with pid %d\n", pid); + exit(EXIT_SUCCESS); + } - // create a new session and process group - if (setsid() == -1) return -1; + // create a new session and process group + if (setsid() == -1) + return -1; - // set the working directory to the root directory - if (chdir("/") == -1) return -1; + // set the working directory to the root directory + if (chdir("/") == -1) + return -1; - // close all open files--NR_OPEN is overkill, but works - for (int i = 0; i < NR_OPEN; i++) { - close(i); - } + // close all open files--NR_OPEN is overkill, but works + for (int i = 0; i < NR_OPEN; i++) { + close(i); + } - // redirect fd's 0,1,2 to /dev/null - open("/dev/null", O_RDWR); // stdin - dup(0); // stdout - dup(0); // stderr + // redirect fd's 0,1,2 to /dev/null + open("/dev/null", O_RDWR); // stdin + dup(0); // stdout + dup(0); // stderr - // do its daemon thing - for (int i = 0; i < 10; i++) { - printf("Hello from daemon %d\n", getpid()); - sleep(1000); - } + // do its daemon thing + for (int i = 0; i < 10; i++) { + printf("Hello from daemon %d\n", getpid()); + sleep(1000); + } - return 0; + return 0; } diff --git a/chp5/session.c b/chp5/session.c index e092c2d..4cbc231 100644 --- a/chp5/session.c +++ b/chp5/session.c @@ -2,8 +2,9 @@ #define _XOPEN_SOURCE 500 #include -int main(void) { - printf("My session id=%d\n", getsid(0)); - printf("My process group id=%d\n", getpgid(0)); - return 0; +int main(void) +{ + printf("My session id=%d\n", getsid(0)); + printf("My process group id=%d\n", getpgid(0)); + return 0; } diff --git a/chp5/system.c b/chp5/system.c index 822de21..0c0203b 100644 --- a/chp5/system.c +++ b/chp5/system.c @@ -1,63 +1,65 @@ #include #define _XOPEN_SOURCE #include -#include #include #include +#include /* my_system - synchronously spawns and waits for the command * "/bin/sh -c ". - * + * * Returns -1 on error of any sort, or the exit code from the * launched process. Does not block or ignore any signals. */ int my_system(const char *); -int main(int argc, char *argv[]) { - if (argc < 2) { - fprintf(stderr, "usage: %s ", argv[0]); - return EXIT_FAILURE; - } - - const char *command = argv[1]; - pid_t pid = fork(); - if (pid == -1) { - perror("fork"); - return EXIT_FAILURE; - } else if (pid > 0) { - int ret = my_system(command); - if (ret == -1) { - fprintf(stderr, "command: \"%s\" error", command); - return EXIT_FAILURE; - } - return ret; - } - - int status; - wait(&status); - return status; +int main(int argc, char *argv[]) +{ + if (argc < 2) { + fprintf(stderr, "usage: %s ", argv[0]); + return EXIT_FAILURE; + } + + const char *command = argv[1]; + pid_t pid = fork(); + if (pid == -1) { + perror("fork"); + return EXIT_FAILURE; + } else if (pid > 0) { + int ret = my_system(command); + if (ret == -1) { + fprintf(stderr, "command: \"%s\" error", command); + return EXIT_FAILURE; + } + return ret; + } + + int status; + wait(&status); + return status; } -int my_system(const char *cmd) { - pid_t pid = fork(); - if (pid == -1) { - return -1; - } else if (pid == 0) { - const char *argv[4]; - argv[0] = "sh"; - argv[1] = "-c"; - argv[2] = cmd; - argv[3] = NULL; +int my_system(const char *cmd) +{ + pid_t pid = fork(); + if (pid == -1) { + return -1; + } else if (pid == 0) { + const char *argv[4]; + argv[0] = "sh"; + argv[1] = "-c"; + argv[2] = cmd; + argv[3] = NULL; - execv("/bin/sh", argv); - exit(-1); - } - - int status; - if (waitpid(pid, &status, 0) == -1) { - return -1; - } else if (WIFEXITED(status)) { - return WEXITSTATUS(status); - } - return -1; + execv("/bin/sh", argv); + exit(-1); + } + + int status; + if (waitpid(pid, &status, 0) == -1) { + return -1; + } else if (WIFEXITED(status)) { + return WEXITSTATUS(status); + } + return -1; } diff --git a/chp5/wait.c b/chp5/wait.c index 990cb45..8480ffc 100644 --- a/chp5/wait.c +++ b/chp5/wait.c @@ -1,31 +1,34 @@ -#include #include #include #include +#include -int main(void) { - if (!fork()) - return 1; +int main(void) +{ + if (!fork()) + return 1; - int status; - pid_t pid = wait(&status); - if (pid == -1) { - perror("wait"); - } + int status; + pid_t pid = wait(&status); + if (pid == -1) { + perror("wait"); + } - printf("pid=%d\n", pid); - - if (WIFEXITED(status)) - printf("Normal termination with exit status=%d\n", WEXITSTATUS(status)); + printf("pid=%d\n", pid); - if (WIFSIGNALED(status)) - printf("Killed by signal=%d%s\n", WTERMSIG(status), WCOREDUMP(status) ? " (dumped core)" : ""); + if (WIFEXITED(status)) + printf("Normal termination with exit status=%d\n", + WEXITSTATUS(status)); - if (WIFSTOPPED(status)) - printf("Stopped by signal=%d\n", WSTOPSIG(status)); + if (WIFSIGNALED(status)) + printf("Killed by signal=%d%s\n", WTERMSIG(status), + WCOREDUMP(status) ? " (dumped core)" : ""); - if (WIFCONTINUED(status)) - printf("Continued\n"); + if (WIFSTOPPED(status)) + printf("Stopped by signal=%d\n", WSTOPSIG(status)); - return 0; + if (WIFCONTINUED(status)) + printf("Continued\n"); + + return 0; } diff --git a/chp6/README.md b/chp6/README.md new file mode 100644 index 0000000..84b7f6d --- /dev/null +++ b/chp6/README.md @@ -0,0 +1,52 @@ +# 📘 Chapter 6 – Advanced Process Management (Summary) +**From _Linux System Programming_ by Robert Love, 2nd Ed.** + +--- + +## 🔄 Process Scheduling +- The kernel scheduler selects **runnable processes** (those not blocked on I/O, etc.). +- Goals: **maximize CPU utilization**, minimize wait time, and ensure fairness :contentReference[oaicite:1]{index=1}. +- Covers **preemptive scheduling**, **timeslices**, and the Linux **Completely Fair Scheduler (CFS)**. +- Explains **processor affinity** and CPU sets: binding processes to specific CPUs for cache performance :contentReference[oaicite:2]{index=2}. + +## 🧭 Yielding the Processor +- `sched_yield()` lets a running process give up the CPU voluntarily. +- Useful in busy-wait loops or when expecting immediate CPU from others :contentReference[oaicite:3]{index=3}. + +## 🎚️ Priorities & Nice Values +- Processes can adjust their priority using **`nice()`**, where lower nice = higher priority. +- Real-time scheduling policies (`SCHED_FIFO`, `SCHED_RR`) grant stronger priority guarantees for time-sensitive tasks :contentReference[oaicite:4]{index=4}. + +## 🧠 Processor Affinity +- **Get/set CPU affinity** with `sched_getaffinity()` and `sched_setaffinity()`. +- Ensures cache affinity, reducing context-switch overhead :contentReference[oaicite:5]{index=5}. + +## ⏱️ Real-Time Scheduling +- Differences between **hard** and **soft real-time** systems. +- Configurable policies: `SCHED_FIFO`, `SCHED_RR`, with real-time priority range 0–99 :contentReference[oaicite:6]{index=6}. +- Care needed: real-time tasks can lead to starvation of normal tasks. + +## 🔒 Resource Limits +- Kernel enforces per-process limits via `setrlimit()`/`getrlimit()`: + - CPU usage (`RLIMIT_CPU`) + - File sizes (`RLIMIT_FSIZE`) + - Number of open files, memory, etc. :contentReference[oaicite:7]{index=7}. +- Helps contain rogue or misbehaving processes, essential for robustness. + +--- + +## ✅ Why It Matters +Advanced control over process scheduling, priorities, affinity, and resource limits is critical for writing: +- Real-time or latency-sensitive applications +- High-performance servers that benefit from core binding +- Robust daemons that avoid resource exhaustion + +This chapter equips systems programmers with the tools to finely tune how tasks interact with the kernel scheduler and manage system impact. + +--- + +## 📚 References +- *Linux System Programming*, 2nd Ed. — Robert Love +- `man 2 sched_setscheduler`, `man 2 setrlimit`, `man 2 sched_getaffinity` +- Wikipedia: [Completely Fair Scheduler](https://en.wikipedia.org/wiki/Completely_Fair_Scheduler) :contentReference[oaicite:8]{index=8} + diff --git a/exercises/mycp/main.c b/exercises/mycp/main.c index a7f999c..97134aa 100644 --- a/exercises/mycp/main.c +++ b/exercises/mycp/main.c @@ -1,69 +1,71 @@ +#include +#include #include #include #include -#include -#include #define BUFF_LEN 4096 +int main(int argc, char *argv[]) +{ + // Check number of arguments + if (argc < 3) { + fprintf(stderr, "Usage: %s SOURCE DEST\n", argv[0]); + return EXIT_FAILURE; + } -int main(int argc, char *argv[]) { - // Check number of arguments - if (argc < 3) { - fprintf(stderr, "Usage: %s SOURCE DEST\n", argv[0]); - return EXIT_FAILURE; - } + // Get arguments + const char *src = argv[1]; + const char *dst = argv[2]; - // Get arguments - const char *src = argv[1]; - const char *dst = argv[2]; + // Open source file in read only mode + int srcfd = open(src, O_RDONLY); + if (srcfd == -1) { + perror("Failed open source file"); + return EXIT_FAILURE; + } - // Open source file in read only mode - int srcfd = open(src, O_RDONLY); - if (srcfd == -1) { - perror("Failed open source file"); - return EXIT_FAILURE; - } - - // Open destination file in write mode, if exists trunc file otherwise create a new file - int dstfd = open(dst, O_WRONLY | O_CREAT | O_TRUNC, 0644); - if (dstfd == -1) { - perror("Failed open destination file"); - if (close(srcfd) == -1) { - perror("Failed close source file"); - } - return EXIT_FAILURE; - } + // Open destination file in write mode, if exists trunc file otherwise + // create a new file + int dstfd = open(dst, O_WRONLY | O_CREAT | O_TRUNC, 0644); + if (dstfd == -1) { + perror("Failed open destination file"); + if (close(srcfd) == -1) { + perror("Failed close source file"); + } + return EXIT_FAILURE; + } - int exit_code = EXIT_SUCCESS; - char buff[BUFF_LEN]; // reading data buffer - ssize_t read_bytes; - while ((read_bytes = read(srcfd, buff, BUFF_LEN)) != 0) { - if (read_bytes == -1) { - // There is an error for reading source file - if (errno == EINTR) continue; - perror("Failed to read source file"); - exit_code = EXIT_FAILURE; - break; - } + int exit_code = EXIT_SUCCESS; + char buff[BUFF_LEN]; // reading data buffer + ssize_t read_bytes; + while ((read_bytes = read(srcfd, buff, BUFF_LEN)) != 0) { + if (read_bytes == -1) { + // There is an error for reading source file + if (errno == EINTR) + continue; + perror("Failed to read source file"); + exit_code = EXIT_FAILURE; + break; + } - // Write buffer at destination file - if (write(dstfd, buff, read_bytes) == -1) { - perror("Error to write to destination file"); - exit_code = EXIT_FAILURE; - break; - } - } + // Write buffer at destination file + if (write(dstfd, buff, read_bytes) == -1) { + perror("Error to write to destination file"); + exit_code = EXIT_FAILURE; + break; + } + } - // Try to close files - if (close(srcfd) == -1) { - perror("Failed to close source file"); - exit_code = EXIT_FAILURE; - } - if (close(dstfd) == -1) { - perror("Failed to close destination file"); - exit_code = EXIT_FAILURE; - } + // Try to close files + if (close(srcfd) == -1) { + perror("Failed to close source file"); + exit_code = EXIT_FAILURE; + } + if (close(dstfd) == -1) { + perror("Failed to close destination file"); + exit_code = EXIT_FAILURE; + } - return exit_code; + return exit_code; } diff --git a/exercises/tree/main.c b/exercises/tree/main.c index 250c3d8..a1ad238 100644 --- a/exercises/tree/main.c +++ b/exercises/tree/main.c @@ -1,15 +1,15 @@ +#include "tree.h" #include #include -#include "tree.h" -int main(int argc, char *argv[]) { - const char *path = (argc > 1) ? argv[1] : "."; +int main(int argc, char *argv[]) +{ + const char *path = (argc > 1) ? argv[1] : "."; - if (print_tree(path, 0) == -1) { - perror("Error traversing directory"); - return EXIT_FAILURE; - } + if (print_tree(path, 0) == -1) { + perror("Error traversing directory"); + return EXIT_FAILURE; + } - return EXIT_SUCCESS; + return EXIT_SUCCESS; } - diff --git a/exercises/tree/tree.c b/exercises/tree/tree.c index 85c5967..00ab535 100644 --- a/exercises/tree/tree.c +++ b/exercises/tree/tree.c @@ -1,35 +1,39 @@ +#include "tree.h" +#include #include #include #include -#include #include #include -#include "tree.h" -int print_tree(const char *path, int depth) { - DIR *dir = opendir(path); - if (!dir) return -1; +int print_tree(const char *path, int depth) +{ + DIR *dir = opendir(path); + if (!dir) + return -1; - struct dirent *entry; - while ((entry = readdir(dir)) != NULL) { - // Skip . and .. - if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) - continue; + struct dirent *entry; + while ((entry = readdir(dir)) != NULL) { + // Skip . and .. + if (strcmp(entry->d_name, ".") == 0 || + strcmp(entry->d_name, "..") == 0) + continue; - for (int i = 0; i < depth; i++) printf(" "); - printf("|-- %s\n", entry->d_name); + for (int i = 0; i < depth; i++) + printf(" "); + printf("|-- %s\n", entry->d_name); - // Construct full path - char full_path[4096]; - snprintf(full_path, sizeof(full_path), "%s/%s", path, entry->d_name); + // Construct full path + char full_path[4096]; + snprintf(full_path, sizeof(full_path), "%s/%s", path, + entry->d_name); - struct stat st; - if (stat(full_path, &st) == 0 && S_ISDIR(st.st_mode)) { - print_tree(full_path, depth + 1); - } - } + struct stat st; + if (stat(full_path, &st) == 0 && S_ISDIR(st.st_mode)) { + print_tree(full_path, depth + 1); + } + } - closedir(dir); - return 0; + closedir(dir); + return 0; } - diff --git a/exercises/tree/tree.h b/exercises/tree/tree.h index ee75897..dc513f7 100644 --- a/exercises/tree/tree.h +++ b/exercises/tree/tree.h @@ -4,4 +4,3 @@ int print_tree(const char *path, int depth); #endif -