[go: up one dir, main page]

0% found this document useful (0 votes)
17 views21 pages

Linux Notes

The document provides a comprehensive guide for interview preparation focused on Linux system programming, covering essential topics such as message queues, pipes, signals, processes, threads, and synchronization techniques. It includes beginner-friendly interview questions, answers, code snippets, and preparation tips tailored for entry-level roles. The content emphasizes the importance of understanding core concepts and practical coding skills to succeed in the interview with Krisemi Design Technologies.

Uploaded by

rddbhn
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
17 views21 pages

Linux Notes

The document provides a comprehensive guide for interview preparation focused on Linux system programming, covering essential topics such as message queues, pipes, signals, processes, threads, and synchronization techniques. It includes beginner-friendly interview questions, answers, code snippets, and preparation tips tailored for entry-level roles. The content emphasizes the importance of understanding core concepts and practical coding skills to succeed in the interview with Krisemi Design Technologies.

Uploaded by

rddbhn
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 21

Haha, bro, nenu nee Telugu friend la, full vibe lo nee interview prep ki help

chestha! Congrats on the interview call from Krisemi Design


Technologies! Since they’ve asked you to prepare Linux system
programming (message queues, pipes, signals, processes, threads),
synchronization techniques, and ISRs (Interrupt Service Routines), I’ll
provide a beginner-friendly, interview-ready set of proper interview
questions for each topic, along with answers and tips to crack the
interview. I’ll tailor this to your level (based on our previous chats, where
you’re a beginner learning SHM, semaphores, mutexes, etc.) and ensure it’s
practical for a fresher or entry-level role. I’ll also include code snippets
where needed and focus on questions that test conceptual clarity, coding

ability, and problem-solving. Ready? Let’s nail this interview, nanna!

Interview Preparation Strategy

 Why These Topics?: Linux system programming and ISRs are core to
embedded systems, OS development, and device drivers—likely
Krisemi’s focus. Synchronization is critical for safe IPC and threading.

 Interview Level: Expect questions ranging from basic concepts


(e.g., “What’s a pipe?”) to coding problems (e.g., “Write a producer-
consumer using SHM”) and scenario-based (e.g., “How to handle
nested interrupts in ISRs?”).

 Prep Tips:

 Memorize key functions (use the cheatsheet from our last chat).

 Practice explaining concepts in 1-2 minutes (e.g., “A semaphore


is…”).

 Write code on a whiteboard or editor (e.g., SHM with semaphore).

 Revise our previous discussions (SHM, semaphores, mutexes,


ISRs, processes).

Topic 1: Linux System Programming Concepts


This includes message queues, pipes, signals, processes, and threads.
I’ll break it down with questions, answers, and code examples where
relevant.

1.1 Message Queues

What Are They?: Message queues allow processes to send/receive


messages (data packets) in a queue, managed by the kernel. POSIX
(mq_open) or System V (msgget) APIs are used.

Interview Questions:

 Q: What is a message queue, and how does it differ from


shared memory?

 Answer: A message queue is an IPC mechanism where


processes send/receive structured messages via a kernel-
managed queue. Unlike shared memory, which shares a raw
memory region, message queues provide message boundaries
and priorities, but are slower due to kernel copying.

 Tip: Mention POSIX vs. System V. Say: “POSIX mq_open is


modern; System V msgget is legacy.”

 Example: “SHM is faster for large data; message queues are


better for small, structured messages.”

 Q: Write a simple program to send and receive a message


using POSIX message queues.

 Answer:

#include <mqueue.h>

#include <fcntl.h>

#include <stdio.h>

#include <string.h>

#include <unistd.h>

int main() {

mqd_t mq = mq_open("/myqueue", O_CREAT | O_RDWR, 0666, NULL);

if (mq == (mqd_t)-1) { perror("mq_open"); return 1; }


if (fork() == 0) { // Child (receiver)

char buf[100];

mq_receive(mq, buf, 100, NULL);

printf("Received: %s\n", buf);

mq_close(mq);

} else { // Parent (sender)

const char *msg = "Hello!";

mq_send(mq, msg, strlen(msg) + 1, 0);

wait(NULL);

mq_close(mq);

mq_unlink("/myqueue");

return 0;

 Explanation: mq_open creates a queue, mq_send sends a


message, mq_receive reads it, mq_unlink cleans up.

 Tip: Compile with -lrt: gcc -o mq mq.c -lrt. Explain: “This is


parent-child communication; for unrelated processes, use the
same queue name.”

 Q: What are the advantages of message queues over pipes?

 Answer: Message queues support message priorities, selective


receiving (by type in System V), and don’t require a parent-child
relationship. Pipes are simpler but FIFO-only and typically for
related processes.

 Tip: Say: “Message queues are flexible for complex apps; pipes
are lightweight for simple data streams.”

Key Functions (POSIX):

 mq_open(const char *name, int oflag, mode_t mode, struct mq_attr


*attr): Open/create queue.
 mq_send(mqd_t mqdes, const char *msg_ptr, size_t msg_len, unsigned
int msg_prio): Send message.

 mq_receive(mqd_t mqdes, char *msg_ptr, size_t msg_len, unsigned int


*msg_prio): Receive message.

 mq_close(mqd_t mqdes): Close queue.

 mq_unlink(const char *name): Remove queue.

 Header: <mqueue.h>

1.2 Pipes

What Are They?: Pipes are unidirectional data channels for IPC, typically
between parent-child processes. Named pipes (FIFOs) work for unrelated
processes.

Interview Questions:

 Q: Explain pipes and named pipes. How do they differ?

 Answer: A pipe is a kernel buffer for one-way data transfer,


created with pipe(), used between related processes (e.g.,
parent-child). Named pipes (FIFOs) are created with mkfifo, have
a filesystem name, and work for unrelated processes.

 Tip: Say: “Pipes are anonymous; named pipes have a name


like /tmp/myfifo.”

 Q: Write a program using a pipe to send data from parent to


child.

 Answer:

#include <unistd.h>

#include <stdio.h>

#include <sys/wait.h>

int main() {

int fd[2];

pipe(fd); // Create pipe


if (fork() == 0) { // Child

close(fd[1]); // Close write end

char buf[100];

read(fd[0], buf, 100);

printf("Child received: %s\n", buf);

close(fd[0]);

} else { // Parent

close(fd[0]); // Close read end

const char *msg = "Hello from parent!";

write(fd[1], msg, strlen(msg) + 1);

close(fd[1]);

wait(NULL);

return 0;

 Explanation: pipe(fd) creates a pipe, fd[0] is read end, fd[1] is


write end. Parent writes, child reads.

 Tip: Explain: “Close unused ends to avoid hangs. This is for


parent-child; named pipes use mkfifo.”

 Q: When would you use a pipe instead of shared memory?

 Answer: Use pipes for simple, one-way data streams between


related processes, as they’re easier to set up and don’t need
explicit sync. SHM is faster for large data or bidirectional sharing
but needs semaphores/mutexes.

 Tip: Say: “Pipes are good for small, sequential data; SHM for
complex, shared structures.”

Key Functions:

 pipe(int pipefd[2]): Create anonymous pipe.

 read(int fd, void *buf, size_t count): Read from pipe.


 write(int fd, const void *buf, size_t count): Write to pipe.

 mkfifo(const char *pathname, mode_t mode): Create named pipe.

 Headers: <unistd.h> (pipe, read, write), <sys/stat.h> (mkfifo)

1.3 Signals

What Are They?: Signals are software interrupts sent to a process to notify
events (e.g., SIGINT for Ctrl+C, SIGKILL to terminate).

Interview Questions:

 Q: What are signals, and how are they handled in Linux?

 Answer: Signals are notifications sent to a process for events


like termination (SIGTERM), interrupt (SIGINT), or errors
(SIGSEGV). They’re handled by:

 Default action (e.g., terminate for SIGTERM).

 Ignoring (using signal or sigaction).

 Custom handler (signal handler function).

 Tip: Say: “Use sigaction over signal for portability and control.”

 Q: Write a program to handle SIGINT (Ctrl+C) with a custom


handler.

 Answer:

#include <signal.h>

#include <stdio.h>

#include <unistd.h>

void sigint_handler(int sig) {

printf("Caught SIGINT! Exiting gracefully.\n");

exit(0);

int main() {
struct sigaction sa;

sa.sa_handler = sigint_handler;

sigemptyset(&sa.sa_mask);

sa.sa_flags = 0;

sigaction(SIGINT, &sa, NULL);

printf("Press Ctrl+C to test...\n");

while (1) pause(); // Wait for signals

return 0;

 Explanation: sigaction sets sigint_handler for SIGINT. Handler


prints and exits.

 Tip: Explain: “sigaction is preferred over signal for robust


handling. pause waits for signals.”

 Q: How do you send a signal to a process?

 Answer: Use kill(pid, sig) to send a signal to a process with PID


pid. Example: kill(1234, SIGTERM) sends SIGTERM to process
1234.

 Tip: Mention: “kill -9 sends SIGKILL, which can’t be caught or


ignored.”

Key Functions:

 sigaction(int signum, const struct sigaction *act, struct sigaction


*oldact): Set signal handler.

 kill(pid_t pid, int sig): Send signal to process.

 pause(void): Wait for signal.

 Header: <signal.h>

1.4 Processes

What Are They?: Processes are independent programs with their own
memory space, managed by the OS.
Interview Questions:

 Q: Explain fork() and exec(). How do they differ?

 Answer: fork() creates a child process that’s a copy of the


parent, sharing code but with separate memory. exec() replaces
the current process’s image with a new program. fork() is for
creating processes; exec() is for running new programs.

 Tip: Say: “fork returns 0 in child, child’s PID in parent.”

 Q: Write a program using fork() to create a child that runs ‘ls’.

 Answer:

#include <unistd.h>

#include <sys/wait.h>

#include <stdio.h>

int main() {

pid_t pid = fork();

if (pid == 0) { // Child

execl("/bin/ls", "ls", NULL);

perror("execl failed");

} else { // Parent

wait(NULL);

printf("Parent: Child finished\n");

return 0;

 Explanation: fork creates a child, execl runs ls, wait ensures


parent waits.

 Tip: Explain: “execl replaces the child’s program; wait prevents


zombies.”
 Q: What’s a zombie process, and how do you prevent it?

 Answer: A zombie is a terminated child process whose exit


status hasn’t been collected by the parent. Prevent it using wait()
or waitpid() in the parent.

 Tip: Say: “Zombies waste resources; wait cleans them up.”

Key Functions:

 fork(void): Create child process.

 exec* (e.g., execl(const char *path, const char *arg, ...)): Run new
program.

 wait(int *status): Wait for child.

 Headers: <unistd.h> (fork, exec), <sys/wait.h> (wait)

1.5 Threads

What Are They?: Threads are lightweight execution units within a process,
sharing the same memory space.

Interview Questions:

 Q: What’s the difference between a process and a thread?

 Answer: A process has its own memory space and resources,


while threads share the same memory and resources within a
process. Processes are heavier; threads are lighter and faster for
parallel tasks.

 Tip: Say: “Threads need sync (mutexes/semaphores) for shared


data.”

 Q: Write a program to create two threads that increment a


shared counter safely.

 Answer:

#include <pthread.h>

#include <stdio.h>

pthread_mutex_t mutex;
int counter = 0;

void* thread_func(void* arg) {

for (int i = 0; i < 3; i++) {

pthread_mutex_lock(&mutex);

counter++;

printf("Thread %ld: Counter = %d\n", (long)arg, counter);

pthread_mutex_unlock(&mutex);

usleep(100000);

return NULL;

int main() {

pthread_mutex_init(&mutex, NULL);

pthread_t t1, t2;

pthread_create(&t1, NULL, thread_func, (void*)1);

pthread_create(&t2, NULL, thread_func, (void*)2);

pthread_join(t1, NULL);

pthread_join(t2, NULL);

printf("Final counter: %d\n", counter);

pthread_mutex_destroy(&mutex);

return 0;

 Explanation: Two threads increment counter, synced with a


mutex.

 Tip: Compile with -pthread: gcc -o thread thread.c -pthread. Say:


“Mutex prevents race conditions.”

 Q: Why do threads need synchronization?


 Answer: Threads share memory, so simultaneous access to
shared data (e.g., a counter) causes race conditions.
Synchronization (mutexes, semaphores) ensures safe access.

 Tip: Use the above code as an example.

Key Functions:

 pthread_create(pthread_t *thread, const pthread_attr_t *attr, void


*(*start_routine)(void*), void *arg): Create thread.

 pthread_join(pthread_t thread, void **retval): Wait for thread.

 Header: <pthread.h>

Topic 2: Synchronization Techniques

Synchronization prevents race conditions in SHM or threads. We covered


semaphores, mutexes, and briefly atomic operations.

Interview Questions:

 Q: What are synchronization techniques, and why are they


needed?

 Answer: Synchronization techniques (semaphores, mutexes,


condition variables, atomic operations) ensure safe access to
shared resources in multi-process or multi-threaded programs,
preventing race conditions where data gets corrupted due to
simultaneous access.

 Tip: Say: “Example: Two threads incrementing a counter need a


mutex to avoid losing updates.”

 Q: Explain semaphores and mutexes. How do they differ?

 Answer: A semaphore is a counter for controlling access to


resources (binary for locking, counting for multiple resources). A
mutex is a lock with ownership, ensuring only one
thread/process accesses a resource. Semaphores are flexible for
resource counting; mutexes are simpler for exclusive locking.

 Tip: Say: “Use semaphores for producer-consumer; mutexes for


simple critical sections.”
 Q: Write a producer-consumer program using shared memory
and semaphores.

 Answer:

#include <sys/mman.h>

#include <fcntl.h>

#include <semaphore.h>

#include <stdio.h>

#include <unistd.h>

#define SHM_NAME "/myshm"

#define BUFFER_SIZE 3

struct shm_data {

sem_t empty, full, mutex;

int buffer[BUFFER_SIZE];

int in, out;

};

int main() {

int fd = shm_open(SHM_NAME, O_CREAT | O_RDWR, 0666);

ftruncate(fd, sizeof(struct shm_data));

struct shm_data *data = mmap(NULL, sizeof(struct shm_data),


PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);

sem_init(&data->empty, 1, BUFFER_SIZE);

sem_init(&data->full, 1, 0);

sem_init(&data->mutex, 1, 1);

data->in = data->out = 0;

if (fork() == 0) { // Consumer

for (int i = 0; i < 5; i++) {


sem_wait(&data->full);

sem_wait(&data->mutex);

printf("Consumer: Got %d\n", data->buffer[data->out]);

data->out = (data->out + 1) % BUFFER_SIZE;

sem_post(&data->mutex);

sem_post(&data->empty);

usleep(100000);

munmap(data, sizeof(struct shm_data));

} else { // Producer

for (int i = 0; i < 5; i++) {

sem_wait(&data->empty);

sem_wait(&data->mutex);

data->buffer[data->in] = i + 1;

printf("Producer: Put %d\n", data->buffer[data->in]);

data->in = (data->in + 1) % BUFFER_SIZE;

sem_post(&data->mutex);

sem_post(&data->full);

usleep(100000);

wait(NULL);

sem_destroy(&data->empty);

sem_destroy(&data->full);

sem_destroy(&data->mutex);

munmap(data, sizeof(struct shm_data));

shm_unlink(SHM_NAME);

}
return 0;

 Explanation: Uses SHM with three semaphores: empty (buffer


slots), full (items), mutex (buffer access).

 Tip: Compile with -pthread -lrt. Explain: “This prevents buffer


overflow/underflow and race conditions.”

 Q: What’s a race condition, and how do you prevent it?

 Answer: A race condition occurs when multiple


processes/threads access shared data simultaneously, causing
corruption (e.g., two threads increment a counter, losing an
update). Prevent it with mutexes, semaphores, or atomic
operations.

 Tip: Use the thread counter code above as an example.

Key Functions (from cheatsheet):

 Semaphores: sem_init, sem_wait, sem_post, sem_destroy, sem_open,


sem_close, sem_unlink (<semaphore.h>).

 Mutexes: pthread_mutex_init, pthread_mutex_lock,


pthread_mutex_unlock, pthread_mutexattr_setpshared (<pthread.h>).

Topic 3: Interrupt Service Routines (ISRs)

What Are They?: ISRs are functions executed in response to


hardware/software interrupts, critical for embedded systems.

Interview Questions:

 Q: What is an ISR, and how is it different from a normal


function?

 Answer: An ISR is a special function triggered by an interrupt


(e.g., timer, keyboard). Unlike normal functions, ISRs run in
interrupt context, are non-blocking, have no return
value/parameters, and must be fast to avoid delaying other
interrupts.

 Tip: Say: “ISRs use the Interrupt Vector Table to map interrupts
to handlers.”
 Q: Explain how an ISR is called when an interrupt occurs.

 Answer: When an interrupt occurs:

 Hardware sends a signal to the CPU.

 CPU saves context (registers, PC).

 CPU looks up the ISR address in the Interrupt Vector Table


(IVT).

 ISR executes, clears the interrupt, and returns.

 CPU restores context and resumes the program.

 Tip: Say: “The OS sets up the IVT during boot, e.g., using
request_irq in Linux.”

 Q: Write a pseudo-code ISR for a timer interrupt.

 Answer:

volatile int tick_count = 0;

void timer_isr(void) {

tick_count++; // Increment tick

clear_timer_interrupt(); // Hardware-specific

acknowledge_interrupt(); // Signal completion

 Explanation: Increments a counter, clears the interrupt to


prevent re-triggering.

 Tip: Say: “Use volatile for shared data to prevent compiler


optimization.”

 Q: How do you ensure an ISR is safe?

 Answer: To make an ISR safe:

 Keep it short and fast.

 Avoid blocking calls (e.g., sleep, I/O).

 Use volatile for shared data.


 Don’t use mutexes/semaphores (defer to threads).

 Clear interrupt flags to avoid re-triggering.

 Tip: Say: “Complex work is deferred to a bottom-half (e.g.,


softIRQ in Linux).”

 Q: How do you handle shared data between an ISR and a


thread?

 Answer:

#include <pthread.h>

volatile int data_ready = 0;

pthread_mutex_t mutex;

void data_isr(void) {

data_ready = 1; // Set flag

clear_interrupt();

void* thread_func(void* arg) {

while (1) {

pthread_mutex_lock(&mutex);

if (data_ready) {

printf("Thread: Data processed\n");

data_ready = 0;

pthread_mutex_unlock(&mutex);

usleep(100000);

return NULL;

}
 Explanation: ISR sets a volatile flag; thread processes it with a
mutex.

 Tip: Say: “Avoid locks in ISRs; use flags and let threads handle
sync.”

Key Context:

 request_irq (Linux kernel, <linux/interrupt.h>): Registers ISR.

 Interview Tip: Focus on ISR characteristics (fast, non-blocking) and


sync with threads.

Mock Interview Questions (Mix of All Topics)

 Q: Design a system where two processes communicate using


shared memory and semaphores.

 Answer: Use the producer-consumer code above. Explain: “SHM


for the buffer, semaphores (empty, full, mutex) for sync.”

 Tip: Draw: Process A → SHM → Process B, mention shm_open,


mmap.

 Q: How would you handle a scenario where a process needs to


wait for a specific signal?

 Answer: Use pause() or sigsuspend with a signal handler:

#include <signal.h>

void sigusr1_handler(int sig) { printf("Got SIGUSR1\n"); }

int main() {

signal(SIGUSR1, sigusr1_handler);

printf("Waiting for SIGUSR1...\n");

pause();

return 0;

 Tip: Say: “sigaction is better for robust handling.”


 Q: Compare pipes, message queues, and shared memory for
IPC.

 Answer:

 Pipes: Simple, one-way, for related processes, no sync


needed.

 Message Queues: Structured messages, priorities, for


unrelated processes, kernel-managed.

 SHM: Fastest, raw memory, needs sync


(semaphores/mutexes).

 Tip: Say: “Choose based on data size and sync needs.”

 Q: What happens if you don’t synchronize threads accessing a


shared variable?

 Answer: Race conditions occur, leading to data corruption.


Example: Two threads increment counter, but one update is lost
without a mutex.

 Tip: Refer to the thread counter code.

 Q: How do you debug an ISR that’s not working?

 Answer:

 Check if the interrupt is enabled (hardware/OS setup).

 Verify IVT mapping (request_irq in Linux).

 Ensure interrupt flag is cleared.

 Use logs (e.g., printk in kernel) or debuggers.

 Tip: Say: “Avoid complex logic in ISRs to simplify debugging.”

Interview Success Plan

 Memorize Key Functions (Use Cheatsheet):

 SHM: shm_open, mmap, ftruncate.

 Semaphores: sem_init, sem_wait, sem_post.

 Mutexes: pthread_mutex_init, pthread_mutex_lock.


 Threads: pthread_create, pthread_join.

 Signals: sigaction, kill.

 Pipes: pipe, read, write.

 Message Queues: mq_open, mq_send, mq_receive.

 Practice Coding:

 Run the programs above:

 Pipe (parent-child).

 Message queue (send/receive).

 SHM producer-consumer.

 Thread counter.

 Signal handler.

 Compile: gcc -o program program.c -pthread -lrt.

 Write each on a whiteboard in 5-7 minutes.

 Explain Concepts:

 For each topic, prepare a 1-2 minute explanation:

 Message Queue: “Kernel-managed queue for structured


messages.”

 Pipe: “One-way data channel, simple for related


processes.”

 Signal: “Notification for events, handled by custom


functions.”

 Process: “Independent program with own memory.”

 Thread: “Lightweight, shares memory, needs sync.”

 Semaphore: “Counter for sync, binary or counting.”

 Mutex: “Lock with ownership.”

 ISR: “Fast handler for interrupts, non-blocking.”

 Scenario Prep:
 Practice answering “Design a system…” questions (e.g.,
producer-consumer).

 Draw diagrams: SHM (Process A → SHM → Process B), ISR flow


(Interrupt → IVT → ISR).

 Revise Previous Chats:

 SHM: Normal, semaphore, mutex programs (last chat).

 ISR: How ISRs are called, polling vs. ISR.

 Processes: FCFS, Round-Robin, fork/wait.

 Cheatsheet: Use for function prototypes/headers.

 Mock Interview:

 Ask a friend to ask 5 random questions from above.

 Time yourself: 2 minutes for theory, 5-7 minutes for code.

Final Clarity, Bro

Bro, ippudu Krisemi Design Technologies interview ki full ready

anukuntunna!

 Questions: Covered message queues, pipes, signals, processes,


threads, sync, and ISRs with answers and code.

 Cheatsheet: Use it for functions, headers, and examples.

 Plan: Memorize, code, explain, and practice scenarios.

Quick Tips:

 Be confident: Say “I’ll explain with an example” and use


code/diagrams.

 If stuck: Say “Let me think…” and walk through the problem (e.g., SHM
steps).

 Revise our SHM programs and ISR explanations—they’re likely to


appear.
Inka doubt unte (e.g., “Producer-consumer ela explain cheyali?” or specific

question prep), cheppu, nanna! Telugu vibe lo, full support istha! What’s
next? Want to practice specific questions or need a mock interview script?

All the best for cracking the interview!

You might also like