1 / 21

System Calls & Signals

System Calls & Signals. setsockopt. Used to set socket options SO_LINGER - Sets or gets the SO_LINGER option. The argument is a linger structure. struct linger { int l_onoff; /* linger active */ int l_linger; /* how many seconds to linger for */ };

napoleona
Download Presentation

System Calls & Signals

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. System Calls & Signals

  2. setsockopt • Used to set socket options • SO_LINGER - Sets or gets the SO_LINGER option. The argument is a linger structure. • struct linger { • int l_onoff; /* linger active */ • int l_linger; /* how many seconds to linger for */ • }; When enabled, a close(2) or shutdown(2) will not return until all queued messages for the socket have been successfully sent or the linger timeout has been reached. • int result; • struct linger linger; • linger.l_onoff = 1; /*0 = off (l_linger ignored), nonzero = on */ • linger.l_linger =1; /* how many seconds to linger for */ • result = setsockopt(s, SOL_SOCKET, SO_LINGER, &linger, sizeof(linger));

  3. Reuseaddr • Normally you have to wait for about 2 minutes to reuse the same port on a machine • This wait is intended to protect the TCP connection protocol from errors • You can override it with reuseaddr • int optval = 1; • setsockopt (s, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)); • bind (s, &sin, sizeof(sin));

  4. stat, fstat, lstat #include <sys/types.h> #include <sys/stat.h> int stat(const char *pathname, struct stat *buf) int fstat(int fd, struct stat *buf) int lstat(const char *pathname, struct stat *buf)

  5. stat int stat(const char *pathname, struct stat *buf) • Obtains information about the file pointed to by pathname. • Read, write or execute permission of the named file is not required, but all directories listed in the path name leading to the file must be searchable.

  6. fstat int fstat(int fd, struct stat *buf) • Obtains the same information about an open file known by the file descriptor fd. int lstat(const char *pathname, struct stat *buf) • like stat() except in the case where the named file is a symbolic link, in which case lstat() returns information about the link, while stat() returns information about the file the link references.

  7. struct stat Struct stat { mode_t st_mode; /* file type and mode (type & permissions) */ ino_t st_ino; /* inode’s number */ dev_t st_dev; /* device number (file system) */ nlink_t st_nlink; /* number of links */ uid_t st_uid; /* user ID of owner */ gid_t st_gid; /* group ID of owner */ off_t st_size; /* size in bytes */ time_t st_atime; /* last access */ time_t st_mtime; /* last modified */ time_t st_ctime; /* last file status change */ long st_blksize; /* I/O block size */ long st_blocks; /* number of blocks allocated */ }

  8. HTTPD and Stat • You need to use stat in order to determine the type of a file, so you know whether to print out the directory if it doesn’t have a index.html file • You need to use stat to determine the content-length to send back on static files. int err = stat(fullpath, &fstats); if (err != 0) { logmessage = (char *)malloc(MAX_MSG_SZ); sprintf(logmessage,"Thread %d: [%s not found - replaced with %s]", threadnum, fullpath, gDocumentNotFoundPage); logQ->Enqueue(logmessage); // If the path is to a non-existent file, replace it with gDocumentNotFoundPage strcpy(fullpath, gDocumentNotFoundPage); sprintf(responseCode, "404 Document Not Found"); } if (fstats.st_mode & S_IFDIR) { AppendDefaultPage(fullpath, url); }

  9. Readdir #include <stdio.h> #include <sys/types.h> #include <dirent.h> main() { int len; DIR *dirp; struct dirent *dp; dirp = opendir("."); while ((dp = readdir(dirp)) != NULL) printf("name %s\n", dp->d_name); (void)closedir(dirp); }

  10. Signals • Introduced in UNIX systems to simplify IPC. • Used by the kernel to notify processes of system events. • A signal is a short message sent to a process, or group of processes, containing the number identifying the signal.

  11. Example Signals • Linux supports 31 non-real-time signals. • POSIX standard defines a range of values for RT signals: • SIGRTMIN 32 … SIGRTMAX (_NSIG-1) in <asm-*/signal.h>

  12. Signal Transmission • Signal sending: • Kernel updates descriptor of destination process. • Signal receiving: • Kernel forces target process to “handle” signal. • Pending signals are sent but not yet received. • Up to one pending signal per type for each process, except for POSIX.4 signals. • Subsequent signals are discarded. • Signals can be blocked, i.e., prevented from being received.

  13. Signal-Related Data Structures • sa_handler specifies the action to be associated with signum. This function receives the signal number as its only argument. • sa_mask gives a mask of signals which should be blocked during execution of the signal handler • sa_flags specifies a set of flags which modify the behavior of the signal handling process (SA_RESTART) struct sigaction { void (*sa_handler)(int); void (*sa_sigaction)(int, siginfo_t *, void *); sigset_t sa_mask; int sa_flags; void (*sa_restorer)(void); }

  14. If you want more information siginfo_t { int si_signo; /* Signal number */ int si_errno; /* An errno value */ int si_code; /* Signal code */ pid_t si_pid; /* Sending process ID */ uid_t si_uid; /* Real user ID of sending process */ int si_status; /* Exit value or signal */ clock_t si_utime; /* User time consumed */ clock_t si_stime; /* System time consumed */ sigval_t si_value; /* Signal value */ int si_int; /* POSIX.1b signal */ void * si_ptr; /* POSIX.1b signal */ void * si_addr; /* Memory location which caused fault */ int si_band; /* Band event */ int si_fd; /* File descriptor */ }

  15. Signal Handling System Calls • int sigaction(int sig, const struct sigaction *act, struct sigaction *oact); • Replaces the old signal() function. • Used to bind a handler to a signal. • Handler should match either • void handler(int); • void handler(int, siginfo_t *info, ucontext_t *uap); • The handler function should match this prototype if the SA_SIGINFO bit is set in flags. It then should be pointed to by the sa_sigaction member of struct sigaction.

  16. #include <stdio.h> #include <stdlib.h> #include <pthread.h> #include <unistd.h> #include <signal.h> #include <sys/types.h> #include <sys/signal.h> void *functionC(void *ptr); void handler (int status); /* definition of signal handler */ int counter = 0; main() { int rc1, rc2; pthread_t thread1, thread2; // First set up the signal handler struct sigaction sigold, signew; signew.sa_handler=handler; sigemptyset(&signew.sa_mask); sigaddset(&signew.sa_mask,SIGINT); signew.sa_flags = SA_RESTART; sigaction(SIGINT,&signew,&sigold); /* Create independent threads each of which will execute functionC */ if( (rc1=pthread_create( &thread1, NULL, &functionC, (void *)1)) ) { printf("Thread creation failed: %d\n", rc1); } if( (rc2=pthread_create( &thread2, NULL, &functionC, (void *)2)) ) { printf("Thread creation failed: %d\n", rc2); } printf("I am parent thread %d[%u]\n", 0,(unsigned int)pthread_self()); pthread_join( thread1, NULL); pthread_join( thread2, NULL); } void handler (int status) { printf("%u received signal %d\n", (unsigned int)pthread_self(), status); } void *functionC(void *ptr) { int thnum = (int)ptr; for(;;) { sleep(1); counter++; // Note: This should be protected by semaphores printf("I am thread %d[%u] counter %d\n",thnum,(unsigned int)pthread_self(), counter); } }

  17. Signal Handlers • To get more information //void handler (int status, siginfo_t *info, ucontext_t *uap); void handler (int status, struct __siginfo *info, void *uap); ……. // First set up the signal handler struct sigaction sigold, signew; signew.sa_sigaction=handler; sigemptyset(&signew.sa_mask); sigaddset(&signew.sa_mask,SIGINT); signew.sa_flags = SA_RESTART | SA_SIGINFO; sigaction(SIGINT,&signew,&sigold); ……. //void handler (int status, siginfo_t *info, ucontext_t *uap) void handler (int status, struct __siginfo *info, void *uap) { printf("[%d]%u received signal %d from %d\n", getpid(), (unsigned int)pthread_self(), status, info->si_pid); }

  18. Sending a Signal • int kill(pid_t pid, int sig); • Causes the signal to be delivered to another process • Example: • kill(pID,SIGKILL); • Signals are defined in /usr/include/sys/signal.h • Example usage: • kill the child you execed if it runs too long • How do we tell if a child runs too long?

  19. Timers • int getitimer(int which, struct itimerval *value); • int setitimer(int which, const struct itimerval *value, struct itimerval *ovalue); • Provide microsecond granularity • Will send SIGALRM every interval struct itimerval { struct timeval it_interval; /* next value */ struct timeval it_value; /* current value */ }; struct timeval { long tv_sec; /* seconds */ long tv_usec; /* microseconds */ };

  20. What have your kids been up to? • int getrusage(int who, struct rusage *usage); • Reports on resource usage by yourself and your children • Also set in • pid_t wait4(pid_t pid, int *stat_loc, int options, struct rusage *rusage); struct rusage { struct timeval ru_utime; /* user time used */ struct timeval ru_stime; /* system time used */ long ru_maxrss; /* maximum resident set size */ long ru_ixrss; /* integral shared memory size */ long ru_idrss; /* integral unshared data size */ long ru_isrss; /* integral unshared stack size */ long ru_minflt; /* page reclaims */ long ru_majflt; /* page faults */ long ru_nswap; /* swaps */ long ru_inblock; /* block input operations */ long ru_oublock; /* block output operations */ long ru_msgsnd; /* messages sent */ long ru_msgrcv; /* messages received */ long ru_nsignals; /* signals received */ long ru_nvcsw; /* voluntary context switches */ long ru_nivcsw; /* involuntary context switches */ };

  21. pID = fork(); if (pID == 0) // child { // Code only executed by child process // exec the program char *argvToChild[5]; char *envToChild[5]; argvToChild[0] = "foo"; argvToChild[1] = "bar"; argvToChild[2] = NULL; envToChild[0] = "SERVER_NAME=gunga"; envToChild[1] = "GUMBO=GIMBO"; envToChild[2] = NULL; printf("Child about to exec\n"); execve("loop.pl",argvToChild,envToChild); perror("Child should not return"); } else // parent { // Code only executed by parent process for(;;); } } void handler (int status) { int stat; int err; struct rusage child_ru; printf("received signal %d\n",status); if(status == SIGCHLD) { err = wait4(pID,&stat,0,&child_ru); printf("wait returned %d status %X exit status %d\n",err,stat, WEXITSTATUS(stat)); printf("user time %d, system time %d\n",child_ru.ru_utime.tv_sec,child_ru.ru_stime.tv_sec); } if(status == SIGALRM) { printf("This guy %d is toast\n",pID); kill(pID,SIGKILL); } } #include <iostream> #include <string> #include <sys/wait.h> #include <sys/types.h> #include <unistd.h> #include <signal.h> #include <sys/types.h> #include <sys/signal.h> #include <time.h> #include <sys/time.h> using namespace std; void handler (int status); /* definition of signal handler */ // Global variable so signal handler can see it pid_t pID; // This example shows how to use execve and signals main() { struct sigaction sigold, signew; struct itimerval rttimer; struct itimerval old_rttimer; signew.sa_handler=handler; sigemptyset(&signew.sa_mask); sigaddset(&signew.sa_mask,SIGCHLD); sigaddset(&signew.sa_mask,SIGALRM); signew.sa_flags = SA_RESTART; sigaction(SIGCHLD,&signew,&sigold); sigaction(SIGALRM,&signew,&sigold); // Now set up the interval timer rttimer.it_value.tv_sec = 10; rttimer.it_value.tv_usec = 0; rttimer.it_interval.tv_sec = 10; rttimer.it_interval.tv_usec = 0; setitimer (ITIMER_REAL, &rttimer, &old_rttimer);

More Related