Embedded Linux System Programming - Unit 3 Notes
1. System Programming Concepts
System programming involves writing code that interacts closely with the operating system. It
includes interacting with hardware, managing memory, handling processes, file I/O, etc.
Key concepts:
- System calls: Functions provided by the OS kernel (e.g., read, write, open, fork)
- Headers: unistd.h (for system calls), fcntl.h (file control), sys/types.h
Example (using write system call):
#include <unistd.h>
int main() {
char msg[] = "Hello, system call!\n";
write(1, msg, sizeof(msg));
return 0;
}
2. File Operation Programming
Linux allows low-level file operations using system calls like open(), read(), write(), close().
Important headers: <fcntl.h>, <unistd.h>
Example:
#include <fcntl.h>
#include <unistd.h>
int main() {
int fd = open("file.txt", O_CREAT | O_WRONLY, 0644);
write(fd, "Linux File I/O\n", 15);
close(fd);
return 0;
}
File permission: 0644 means -rw-r--r--
3. I/O Operation Programming
Working with low-level I/O operations using system calls like read() and write().
read(fd, buffer, size): Reads size bytes from fd to buffer
write(fd, buffer, size): Writes size bytes from buffer to fd
Example:
char buf[100];
int n = read(fd, buf, 100); // Reads 100 bytes from fd
write(1, buf, n); // Writes to stdout
4. Advanced Process Management Programming
Includes fork(), exec(), wait(), exit(), zombie and orphan processes.
- fork(): creates a new child process
- exec(): replaces current process image
- wait(): waits for child to finish
- exit(), _exit(): terminates process (exit flushes I/O buffers, _exit doesn't)
Headers: <sys/types.h>, <sys/wait.h>, <unistd.h>
Example:
#include <unistd.h>
#include <sys/wait.h>
int main() {
pid_t pid = fork();
if (pid == 0) {
execlp("ls", "ls", NULL);
} else {
wait(NULL);
printf("Child finished\n");
}
return 0;
}
5. Thread Programming and Mutex
POSIX threads (pthreads) are used for multithreading.
pthread_create(): creates a thread
pthread_join(): waits for thread to finish
pthread_mutex_*(): used to protect critical sections
Example:
#include <pthread.h>
int counter = 0;
pthread_mutex_t lock;
void* increment(void* arg) {
for (int i = 0; i < 100000; i++) {
pthread_mutex_lock(&lock);
counter++;
pthread_mutex_unlock(&lock);
}
return NULL;
}
int main() {
pthread_t t1, t2;
pthread_mutex_init(&lock, NULL);
pthread_create(&t1, NULL, increment, NULL);
pthread_create(&t2, NULL, increment, NULL);
pthread_join(t1, NULL);
pthread_join(t2, NULL);
pthread_mutex_destroy(&lock);
printf("Counter: %d\n", counter);
return 0;
}
Follow-up Q&A
Q1: Why are void* used in pthreads?
A: To allow passing of any type of data to threads in a generic way.
Q2: Can exec() be used without fork()?
A: Yes, but it replaces the current process. After exec(), the original program stops running.
Q3: exit() vs _exit()?
A: exit() flushes stdio buffers and calls cleanup handlers, _exit() terminates immediately without
flushing.
Q4: What is flushing of buffers?
A: Writing any remaining data in memory (like printf's output) to their destination before process
exits.
Q5: What is a Race Condition?
A: A bug that occurs when threads access shared data without synchronization, causing
unpredictable results.
Q6: What is a Mutex?
A: A mutual exclusion object that prevents multiple threads from accessing critical section at the
same time.