From e29fa7be44face34ac76f8609c1b479779f0d308 Mon Sep 17 00:00:00 2001 From: Saturneric Date: Mon, 11 Jan 2021 18:00:36 +0800 Subject: [PATCH] 9\10\11\12 Finished. --- 10/signal/pause.c | 16 +++++++ 10/signal/pause2.c | 20 +++++++++ 10/signal/pending.c | 50 ++++++++++++++++++++++ 10/signal/read.c | 35 +++++++++++++++ 10/signal/recall.c | 32 ++++++++++++++ 10/signal/signal.c | 34 +++++++++++++++ 10/signal/sleep.c | 38 +++++++++++++++++ 10/signal/suspend.c | 48 +++++++++++++++++++++ 10/signal/system.c | 59 ++++++++++++++++++++++++++ 11/pthread/thread_clean.c | 68 +++++++++++++++++++++++++++++ 11/pthread/thread_exit.c | 46 ++++++++++++++++++++ 11/pthread/thread_id.c | 33 +++++++++++++++ 11/pthread/thread_timedlock.c | 36 ++++++++++++++++ 12/attr/atfork.c | 80 +++++++++++++++++++++++++++++++++++ 12/attr/makethread.c | 30 +++++++++++++ 9/processGroup/orphan.c | 46 ++++++++++++++++++++ 16 files changed, 671 insertions(+) create mode 100644 10/signal/pause.c create mode 100644 10/signal/pause2.c create mode 100644 10/signal/pending.c create mode 100644 10/signal/read.c create mode 100644 10/signal/recall.c create mode 100644 10/signal/signal.c create mode 100644 10/signal/sleep.c create mode 100644 10/signal/suspend.c create mode 100644 10/signal/system.c create mode 100644 11/pthread/thread_clean.c create mode 100644 11/pthread/thread_exit.c create mode 100644 11/pthread/thread_id.c create mode 100644 11/pthread/thread_timedlock.c create mode 100644 12/attr/atfork.c create mode 100644 12/attr/makethread.c create mode 100644 9/processGroup/orphan.c diff --git a/10/signal/pause.c b/10/signal/pause.c new file mode 100644 index 0000000..1c46a80 --- /dev/null +++ b/10/signal/pause.c @@ -0,0 +1,16 @@ +#include +#include +#include + +static void sig_alarm(int signo) { + +} + +int main(void) { + if(signal(SIGALRM, sig_alarm) == SIG_ERR) + return -1; + + alarm(3); + pause(); + return alarm(0); +} diff --git a/10/signal/pause2.c b/10/signal/pause2.c new file mode 100644 index 0000000..adf00b6 --- /dev/null +++ b/10/signal/pause2.c @@ -0,0 +1,20 @@ +#include +#include +#include +#include + +static jmp_buf env_alrm; + +static void sig_alrm(int signo) { + longjmp(env_alrm, 1); +} + +int main(void) { + if(signal(SIGALRM, sig_alrm) == SIG_ERR) + return -1; + if(setjmp(env_alrm) == 0) { + alarm(3); + pause(); + } + return 0; +} diff --git a/10/signal/pending.c b/10/signal/pending.c new file mode 100644 index 0000000..8368c70 --- /dev/null +++ b/10/signal/pending.c @@ -0,0 +1,50 @@ +#include +#include +#include +#include + +static void sig_quit(int); + +int main(void) { + sigset_t newmask, oldmask, pendmask; + + if (signal(SIGQUIT, sig_quit) == SIG_ERR) { + printf("can't catch SIGQUIT\n"); + return -1; + } + + sigemptyset(&newmask); + sigaddset(&newmask, SIGQUIT); + if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0) { + printf("SIG_BLOCK error\n"); + return -1; + } + + sleep(5); + + if (sigpending(&pendmask) < 0) { + printf("sigpeding error\n"); + return -1; + } + if (sigismember(&pendmask, SIGQUIT)) { + printf("\nSIGQUIT pending\n"); + } + + if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0) { + printf("SIG_SETMASK error\n"); + return -1; + } + + printf("SIGQUIT unblocked\n"); + + sleep(5); + + return 0; +} + +static void sig_quit(int signo) { + printf("caught SIGQUIT\n"); + if (signal(SIGQUIT, SIG_DFL) == SIG_ERR) { + printf("can't reset SIGQUIT"); + } +} diff --git a/10/signal/read.c b/10/signal/read.c new file mode 100644 index 0000000..3bb947c --- /dev/null +++ b/10/signal/read.c @@ -0,0 +1,35 @@ +#include +#include +#include +#include + +static void sig_alrm(int); +static jmp_buf env_alrm; + +int main(void) { + int n; + char line[256]; + + if(signal(SIGALRM, sig_alrm) == SIG_ERR) { + printf("signal(SIGALRM) error\n"); + return -1; + } + + if(setjmp(env_alrm) != 0) { + printf("read timeout\n"); + return -1; + } + + alarm(5); + if((n = read(STDIN_FILENO, line, 256) < 0)) { + printf("read error\n"); + return -1; + } + alarm(0); + write(STDOUT_FILENO, line, n); + return 0; +} + +static void sig_alrm(int signo) { + longjmp(env_alrm, 1); +} diff --git a/10/signal/recall.c b/10/signal/recall.c new file mode 100644 index 0000000..370b185 --- /dev/null +++ b/10/signal/recall.c @@ -0,0 +1,32 @@ +#include +#include +#include +#include +#include +#include + +static void my_alarm(int signo) { + struct passwd *rootptr; + + printf("in signal handler signo = %d\n", signo); + if ((rootptr = getpwnam("root")) == NULL) { + printf("getpwnam(root) error"); + } + + alarm(1); +} + +int main(void) { + struct passwd *ptr; + + signal(SIGALRM, my_alarm); + alarm(1); + + for(;;) { + if((ptr = getpwnam("eric")) == NULL) + printf("getpwnam(eric) error"); + if(strcmp(ptr->pw_name, "eric") != 0) { + printf("return value corrupted, pw_name = %s\n", ptr->pw_name); + } + } +} diff --git a/10/signal/signal.c b/10/signal/signal.c new file mode 100644 index 0000000..b4812a6 --- /dev/null +++ b/10/signal/signal.c @@ -0,0 +1,34 @@ +#include +#include +#include +#include +#include + +static void sig_usr(int); + +int main(void) { + if(signal(SIGUSR1, sig_usr) == SIG_ERR) { + printf("can't catch SIGUSR1\n"); + exit(-1); + } + if(signal(SIGUSR2, sig_usr) == SIG_ERR) { + printf("can't catch SIGUSR2\n"); + exit(-1); + } + + for(;;) + pause(); + + return 0; +} + +static void sig_usr(int signo) { + if(signo == SIGUSR1) { + printf("SIGUSR1 received\n"); + } + else if(signo == SIGUSR2) { + printf("SIGUSR2 recieved\n"); + } + else + printf("error %d received", signo); +} diff --git a/10/signal/sleep.c b/10/signal/sleep.c new file mode 100644 index 0000000..1bf24d6 --- /dev/null +++ b/10/signal/sleep.c @@ -0,0 +1,38 @@ +#include +#include + +static void sig_alrm(int signo) { + +} + +unsigned int sleep(unsigned int seconds) { + struct sigaction newact, oldact; + sigset_t newmask, oldmask, suspmask; + unsigned int unslept; + + newact.sa_handler = sig_alrm; + sigemptyset(&newact.sa_mask); + newact.sa_flags = 0; + sigaction(SIGALRM, &newact, &oldact); + + sigemptyset(&newmask); + sigaddset(&newmask, SIGALRM); + sigprocmask(SIG_BLOCK, &newmask, &oldmask); + + alarm(seconds); + suspmask = oldmask; + + sigdelset(&suspmask, SIGALRM); + sigsuspend(&suspmask); + unslept = alarm(0); + + sigaction(SIGALRM, &oldact, NULL); + + sigprocmask(SIG_SETMASK, &oldmask, NULL); + return unslept; + +} + +int main(void) { + return sleep(5); +} diff --git a/10/signal/suspend.c b/10/signal/suspend.c new file mode 100644 index 0000000..99bdd01 --- /dev/null +++ b/10/signal/suspend.c @@ -0,0 +1,48 @@ +#include +#include +#include +#include + +static void sig_int(int); + +int main(void) { + sigset_t newmask, oldmask, waitmask; + + printf("program start\n"); + + if(signal(SIGINT, sig_int) == SIG_ERR) { + printf("signal(SIGINT) error\n"); + return -1; + } + sigemptyset(&waitmask); + sigaddset(&waitmask, SIGUSR1); + sigemptyset(&newmask); + sigaddset(&newmask, SIGINT); + + if(sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0) { + printf("SIG_BLOCK error\n"); + return -1; + } + + printf("in critical region\n"); + + if(sigsuspend(&waitmask) != -1) { + printf("sigsuspend error\n"); + return -1; + } + + printf("after return from sigsuspend\n"); + + if(sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0){ + printf("SIG_SETMASK error\n"); + return -1; + } + + printf("program exit\n"); + + return 0; +} + +static void sig_int(int signo) { + printf("caught sigint = %d\n", signo); +} diff --git a/10/signal/system.c b/10/signal/system.c new file mode 100644 index 0000000..a6b1d18 --- /dev/null +++ b/10/signal/system.c @@ -0,0 +1,59 @@ +#include +#include +#include +#include + +int system(const char *cmdstring) { + pid_t pid; + int status; + struct sigaction ignore, saveintr, savequit; + sigset_t chldmask, savemask; + + if (cmdstring == NULL) + return 1; + + ignore.sa_handler = SIG_IGN; + sigemptyset(&ignore.sa_mask); + ignore.sa_flags = 0; + if (sigaction(SIGINT, &ignore, &saveintr) < 0) + return -1; + if (sigaction(SIGQUIT, &ignore, &savequit) < 0) + return -1; + sigemptyset(&chldmask); + sigaddset(&chldmask, SIGCHLD); + if (sigprocmask(SIG_BLOCK, &chldmask, &savemask) < 0) + return -1; + + if((pid = fork()) < 0) { + status = -1; + } + else if (pid == 0) { + sigaction(SIGINT, &saveintr, NULL); + sigaction(SIGQUIT, &savequit, NULL); + execl("/bin/sh", "sh", "-c", cmdstring, (char *)0); + _exit(127); + } + else { + while (waitpid(pid, &status, 0) < 0) + if (errno != EINTR) { + return -1; + break; + } + } + + if(sigaction(SIGINT, &saveintr, NULL) < 0) { + return -1; + } + if(sigaction(SIGQUIT, &savequit, NULL) < 0) { + return -1; + } + if(sigprocmask(SIG_SETMASK, &savemask, NULL) < 0) { + return -1; + } + + return status; +} + +int main(void) { + return system("ls ."); +} diff --git a/11/pthread/thread_clean.c b/11/pthread/thread_clean.c new file mode 100644 index 0000000..823e7f8 --- /dev/null +++ b/11/pthread/thread_clean.c @@ -0,0 +1,68 @@ +#include +#include +#include +#include + +void cleanup(void *arg) { + printf("cleanup: %s\n", (char *) arg); +} + +void *thr_fn1(void *arg) { + printf("thread 1 start\n"); + pthread_cleanup_push(cleanup, (void *)"thread 1 first handler"); + pthread_cleanup_push(cleanup, (void *)"thread 1 second handler"); + + printf("thread 1 push complete\n"); + if(arg) { + return (void *)1; + } + pthread_cleanup_pop(0); + pthread_cleanup_pop(0); + return (void *)1; +} + +void *thr_fn2(void *arg) { + printf("thread 2 start\n"); + pthread_cleanup_push(cleanup, (void *)"thread 2 first handler"); + pthread_cleanup_push(cleanup, (void *)"thread 2 second handler"); + + printf("thread 2 push complete\n"); + if(arg) { + pthread_exit((void *)2); + } + pthread_cleanup_pop(0); + pthread_cleanup_pop(0); + pthread_exit((void *)2); +} + +int main(void) { + int err; + pthread_t tid1, tid2; + void *tret; + + err = pthread_create(&tid1, NULL, thr_fn1, (void *)1); + if(err != 0) { + printf("thread 1 create error\n"); + return -1; + } + + err = pthread_create(&tid2, NULL, thr_fn2, (void *)1); + if(err != 0) { + printf("thread 2 create error\n"); + return -1; + } + + err = pthread_join(tid1, &tret); + if(err != 0) { + printf("thread 1 join error\n"); + return -1; + } + printf("thread 1 exit code %ld\n", (long)tret); + err = pthread_join(tid2, &tret); + if(err != 0) { + printf("thread 2 join error\n"); + return -1; + } + printf("thread 2 exit code %ld\n", (long)tret); + return 0; +} diff --git a/11/pthread/thread_exit.c b/11/pthread/thread_exit.c new file mode 100644 index 0000000..43625a7 --- /dev/null +++ b/11/pthread/thread_exit.c @@ -0,0 +1,46 @@ +#include +#include +#include +#include + +void *thr_fn1(void *arg) { + printf("thread 1 returning\n"); + return (void *)1; +} + +void *thr_fn2(void *arg) { + printf("thread 2 exiting\n"); + pthread_exit((void *)2); +} + +int main(void) { + int err; + pthread_t tid1, tid2; + void *tret; + + err = pthread_create(&tid1, NULL, thr_fn1, NULL); + if(err != 0) { + printf("thread 1 create error\n"); + return -1; + } + + err = pthread_create(&tid2, NULL, thr_fn2, NULL); + if(err != 0) { + printf("thread 2 create error\n"); + return -1; + } + + err = pthread_join(tid1, &tret); + if(err != 0) { + printf("thread 1 join error\n"); + return -1; + } + printf("thread 1 exit code %ld\n", (long)tret); + err = pthread_join(tid2, &tret); + if(err != 0) { + printf("thread 2 join error\n"); + return -1; + } + printf("thread 2 exit code %ld\n", (long)tret); + return 0; +} diff --git a/11/pthread/thread_id.c b/11/pthread/thread_id.c new file mode 100644 index 0000000..7ca6854 --- /dev/null +++ b/11/pthread/thread_id.c @@ -0,0 +1,33 @@ +#include +#include +#include +#include + +pthread_t ntid; + +void printids(const char *s) { + pid_t pid; + pthread_t tid; + + pid = getpid(); + tid = pthread_self(); + printf("%s pid %lu tid %lu (0x%lx)\n", s, (unsigned long) pid, (unsigned long) tid, (unsigned long) tid); +} + +void *thr_fn(void *arg) { + printids("new thread:"); + return (void *)0; +} + +int main(void) { + int err; + + err = pthread_create(&ntid, NULL, thr_fn, NULL); + if(err != 0) { + printf("create thread error\n"); + return -1; + } + printids("main thread:"); + sleep(1); + return 0; +} diff --git a/11/pthread/thread_timedlock.c b/11/pthread/thread_timedlock.c new file mode 100644 index 0000000..7e97029 --- /dev/null +++ b/11/pthread/thread_timedlock.c @@ -0,0 +1,36 @@ +#include +#include +#include +#include +#include +#include + +int main(void) { + int err; + struct timespec tout; + struct tm *tmp; + char buf[64]; + + pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; + pthread_mutex_lock(&lock); + printf("mutex is locked\n"); + clock_gettime(CLOCK_REALTIME, &tout); + tmp = localtime(&tout.tv_sec); + strftime(buf, sizeof(buf), "%r", tmp); + printf("current time is %s\n", buf); + + tout.tv_sec += 10; + + err = pthread_mutex_timedlock(&lock, &tout); + clock_gettime(CLOCK_REALTIME, &tout); + tmp = localtime(&tout.tv_sec); + strftime(buf, sizeof(buf), "%r", tmp); + + printf("the time is now %s\n", buf); + if(err == 0) + printf("mutex locked again!n"); + else + printf("can't lock mutex again: %s\n", strerror(err)); + + return 0; +} diff --git a/12/attr/atfork.c b/12/attr/atfork.c new file mode 100644 index 0000000..b91abc0 --- /dev/null +++ b/12/attr/atfork.c @@ -0,0 +1,80 @@ +#include +#include +#include +#include + +pthread_mutex_t lock1 = PTHREAD_MUTEX_INITIALIZER; +pthread_mutex_t lock2 = PTHREAD_MUTEX_INITIALIZER; + +void prepare(void) { + + int err; + + printf("preparing locks...\n"); + if((err = pthread_mutex_lock(&lock1) != 0)) { + printf("mutex lock error\n"); + } + if((err = pthread_mutex_lock(&lock2)) != 0) { + printf("mutex lock error\n"); + } +} + +void parent(void) { + + int err; + + printf("parent unlocking locks...\n"); + if((err = pthread_mutex_unlock(&lock1)) != 0) + printf("mutex unlock error\n"); + if((err = pthread_mutex_unlock(&lock2)) != 0) + printf("mutex unlock error\n"); +} + +void child(void) { + + int err; + + printf("child unlocking locks...\n"); + if((err = pthread_mutex_unlock(&lock1)) != 0) + printf("mutex unlock error\n"); + if((err = pthread_mutex_unlock(&lock2)) != 0) + printf("mutex unlock error\n"); +} + +void * thr_fn(void *arg) { + printf("thread started...\n"); + pause(); + return 0; +} + +int main(void) { + int err; + pid_t pid; + pthread_t tid; + + if((err = pthread_atfork(prepare, parent, child)) != 0) { + printf("install fork handlers error\n"); + return -1; + } + if((err = pthread_create(&tid, NULL, thr_fn, 0)) != 0) { + printf("create thread error\n"); + return -1; + } + + sleep(2); + printf("parent about to fork...\n"); + + if((pid = fork()) < 0) { + printf("fork failed\n"); + return -1; + } + else if (pid == 0) { + printf("child return from fork\n"); + return 0; + } + else { + printf("parent return from fork\n"); + return 0; + } + return 0; +} diff --git a/12/attr/makethread.c b/12/attr/makethread.c new file mode 100644 index 0000000..183f301 --- /dev/null +++ b/12/attr/makethread.c @@ -0,0 +1,30 @@ +#include +#include +#include +#include + +int makethread(void *(*fn)(void *), void *arg) { + int err; + pthread_t tid; + pthread_attr_t attr; + + err = pthread_attr_init(&attr); + if(err != 0) + return err; + err = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + if(err == 0) + err = pthread_create(&tid, &attr, fn, arg); + pthread_attr_destroy(&attr); + return err; +} + +void *td_fn(void *arg) { + printf("thread executing\n"); + pthread_exit(NULL); +} + +int main(void) { + int err = makethread(td_fn, NULL); + sleep(3); + return err; +} diff --git a/9/processGroup/orphan.c b/9/processGroup/orphan.c new file mode 100644 index 0000000..46ae5a8 --- /dev/null +++ b/9/processGroup/orphan.c @@ -0,0 +1,46 @@ +#include +#include +#include +#include +#include + +static void sig_hup(int singo) { + printf("SIGHUP received, pid = %ld, signo = %d\n", (long) getpid(), singo); +} + +static void pr_ids(char * name) { + printf("%s: pid = %ld, ppid = %ld, pgrp = %ld, tpgrp = %ld\n", + name, (long)getpid(), (long)getppid(), (long)getpgrp(), (long)tcgetpgrp(STDIN_FILENO)); + + fflush(stdout); +} + +int main(void) { + char c; + pid_t pid; + + pr_ids("parent"); + + if((pid = fork()) < 0) { + printf("fork error\n"); + exit(-1); + } + else if (pid > 0) { + printf("parent sleep...\n"); + sleep(3); + printf("parent exit.\n"); + } + else { + pr_ids("child"); + signal(SIGHUP, sig_hup); + kill(getpid(), SIGTSTP); + pr_ids("child2"); + if(read(STDIN_FILENO, &c, 1) != 1){ + printf("read error %d on controlling TTY\n", errno); + exit(-1); + } + exit(0); + } + + return 0; +}