Skip to content

Commit

Permalink
keeping practicing
Browse files Browse the repository at this point in the history
  • Loading branch information
yusufarsln98 committed Apr 12, 2023
1 parent ac7e490 commit 5c843d2
Show file tree
Hide file tree
Showing 11 changed files with 428 additions and 3 deletions.
7 changes: 5 additions & 2 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
{
"files.associations": {
"types.h": "c"
}
"types.h": "c",
"stdio.h": "c",
"unistd.h": "c"
},
"C_Cpp.errorSquiggles": "disabled"
}
58 changes: 58 additions & 0 deletions CSE344 - System Programming/Coding Practices/berru.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// This example replaces the signal mask and then suspends execution.
#define _POSIX_SOURCE
#include <stdio.h>
#include <signal.h>
#include <time.h>
#include <unistd.h>

void catcher(int signum)
{
switch (signum)
{
case SIGUSR1:
puts("catcher caught SIGUSR1");
break;
case SIGUSR2:
puts("catcher caught SIGUSR2");
break;
default:
printf("catcher caught unexpected signal %d\n", signum); // bad idea to call printf in handler
}
}

int main()
{
sigset_t sigset;
struct sigaction sact;
time_t t;

if (fork() == 0)
{
sleep(10);
puts("child is sending SIGUSR2 signal which should be blocked");
kill(getppid(), SIGUSR2);
sleep(5);
puts("child is sending SIGUSR1 signal which should be caught");
kill(getppid(), SIGUSR1);
exit(0);
}

sigemptyset(&sact.sa_mask);
sact.sa_flags = 0;
sact.sa_handler = catcher;

if (sigaction(SIGUSR1, &sact, NULL) != 0)
perror("1st sigaction() error");

if (sigaction(SIGUSR2, &sact, NULL) != 0)
perror("2nd sigaction() error");

sigfillset(&sigset);
sigdelset(&sigset, SIGUSR1);
time(&t);
printf("parent waiting for child to send SIGUSR1 at %s", ctime(&t));
if (sigsuspend(&sigset) == -1) // blocks all except for SIGUSR1
perror("sigsuspend () returned -1 as expected");

printf("sigsuspend is over at %s", ctime(time(&t)));
}
Binary file not shown.
5 changes: 5 additions & 0 deletions CSE344 - System Programming/Coding Practices/practice16.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@
#include <stdlib.h>
#include <signal.h>
// int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
/*
how: SIG_BLOCK, SIG_UNBLOCK, SIG_SETMASK
set: the signal set to be added, removed, or set
oldset: the previous signal mask
*/
#include <unistd.h>

void critical_operation()
Expand Down
2 changes: 1 addition & 1 deletion CSE344 - System Programming/Coding Practices/practice18.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// signal handlers
// --- --- SIGNAL HANDLING --- ---
// sigaction() (DO NOT USE signal() system call)

#include <signal.h>
Expand Down
112 changes: 112 additions & 0 deletions CSE344 - System Programming/Coding Practices/practice21.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
// waiting for signals...
// ! Important !
/*
Busy waiting is a method of waiting for a signal to occur.
Using busy waiting is easy, however,
CPU usage will be 100%.
When this happens, other processes will not be able to run.
! Do not use busy waiting !
-- from slides --
busy waiting: testing continuously (within a loop) whether
a certain event occurred by using CPU cycles.
The alternative is to suspend the process until a signal arrives
notifying it that the event occurred (hence the CPU is free).
POSIX system calls for suspending process until a signal occurs:
- sleep (NO) x
- nanosleep (NO) x
- pause (NO) x
- sigsuspend (YES) v
*/

/*
sleep() and nanosleep() (BAD PRACTICE)
Returns 0 on normal completion, or number of unslept seconds if
prematurely terminated.
#include <unistd.h>
--> unsigned int sleep(unsigned int seconds);
nanosleep is a more powerful version of sleep that operates at higher
resolution.
*/

/*
pause() (BAD PRACTICE)
Suspends the process until a signal is received. (or an unhandled signal terminates the process)
Always returns -1 and sets errno to EINTR.
#include <unistd.h>
--> int pause(void);
for (;;) // infinite loop
pause(); // wait for a signal
*/

// Why pause() is insufficient?

#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>

void handler(int sig)
{
printf("Ouch!\n");
}

int main()
{
sigset_t prevMask, intMask;
struct sigaction sa; // action to be taken when a signal is received

// add SIGINT to the mask set
sigemptyset(&intMask);
sigaddset(&intMask, SIGINT);

// Handle SIGINT (action)
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
sa.sa_handler = &handler;

// sig num, action, old action
if (sigaction(SIGINT, &sa, NULL) == -1)
{
perror("sigaction");
exit(EXIT_FAILURE);
}

/* Block SIGINT prior to execut ing critical section. (At this
point we assume that SIGINT is not already blocked.) */
if (sigprocmask(SIG_BLOCK, &intMask, &prevMask) == -1)
{
perror("sigprocmask - SIG_BLOCK");
exit(EXIT_FAILURE);
}

/* Critical section : do some work here that must not be
interrupted by the SIGINT handler */
printf("Critical section time starts now...\n");
sleep(3);
printf("Critical section time ends now...\n");

/* End of critical section - restore old mask to unblock SIGINT */
if (sigprocmask(SIG_SETMASK, &prevMask, NULL) == -1)
{
perror("sigprocmask - SIG_SETMASK");
exit(EXIT_FAILURE);
}

/* BUG:
what if SIGINT arrives now... (BURADA GELIRSE SICTIK) */

pause(); // Wait for SIGINT
}
96 changes: 96 additions & 0 deletions CSE344 - System Programming/Coding Practices/practice22.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
// sigsuspend (WAITING FOR SIGNALS) example

/*
#include <signal.h>
int sigsuspend(const sigset_t *mask);
// returns -1 with errno set to EINTR
!! Main Idea !!
block the process efficiently until a certain signal arrives and is handled.
Atomically unblocks a signal and suspends the process.
[Atomically: the process is blocked from receiving signals until
the process is suspended. -Copilot]
Equivalent to (atomic):
// Assign new mask and get old mask
sigprocmask(SIG_SETMASK, mask, &oldMask);
pause();
// Restore old mask
sigprocmask(SIG_SETMASK, &oldMask, NULL);
sigsuspend() does these 3 operations atomically.
- block the process from receiving signals
- suspend the process
- restore the old mask automatically after an unmasked signal
is received.
Thanks to sigsuspend(),
- we can avoid busy waiting
- two processes can synchronize themselves where one process
waits for a signal from the other process.
*/

// --- Issues Can Be Encountered ---
/*
1- Handling Errors
// take a backup of errno
void my_handler(int sig)
{
int esaved = errno; // save errno
// do something
errno = esaved; // restore errno
}
*/

/*
2- System Calls Interrupted by a Signal
while((cnt = read(fd, buf, BUF_SIZE)) == -1 && errno == EINTR)
continue; // Do nothing loop body
if (cnt == -1)
perror("read")
-- Create a macro to handle this issue --
#define NO_EINTR(stmt) while ((stmt) == -1 && errno == EINTR);
NO_EINTR(cnt = read(fd, buf, BUF_SIZE));
if (cnt == -1)
perror("read");
*/

/*
3- Signal Handler Function Risks
- Do not call any function that is not async-signal-safe
from a signal handler function.
(e.g. printf, malloc, free, etc.)
- Do not use global variables in a signal handler function.
What to do?
Try to use as few instructions as possible in a signal handler function.
Do not use C library functions.
* Keep function short
If you need to use a C library function do them in the main program
pseduo code:
signal_handler:
sets a flag variable to indicate that a signal has been received
main:
loop:
do lengthy work
if (flag variable is set)
do something (for example: exit)
end loop
*/
44 changes: 44 additions & 0 deletions CSE344 - System Programming/Coding Practices/practice23.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// How to create a process

// system() (not a system call)

/*
#include <stdlib.h>
--> int system(const char *command);
1- runs the shell
2- executes the command
so, it creates 2 processes.
Therefore, it is not efficient.
It is not secure beacuse,
since it uses the shell,
it is as secure as the shell.
*/

// !! Unsafe !!
#include <stdio.h>
#include <stdlib.h>

int main()
{
int return_value;

return_value = system("ls");

return return_value;
}

// What to use instead
/*
Creating process by system calls has 2 steps:
1- fork()
2- exec()
`fork`: that creates a child process that is an exact copy of its parent process.
`exec`: causees a particular process to cease (terminate) being an instance
of one program to installed become instance of a program
*/
Loading

0 comments on commit 5c843d2

Please sign in to comment.