{"id":247,"date":"2020-08-18T19:23:47","date_gmt":"2020-08-18T20:23:47","guid":{"rendered":"http:\/\/www.linux-tutorial.info\/?page_id=77"},"modified":"2020-08-22T19:26:02","modified_gmt":"2020-08-22T20:26:02","slug":"this-is-the-page-title-toplevel-82","status":"publish","type":"page","link":"http:\/\/www.linux-tutorial.info\/?page_id=247","title":{"rendered":"Interrupts Exceptions and Traps"},"content":{"rendered":"\n<title>Interrupts Exceptions and Traps<\/title>\n<p>\nNormally, processes are asleep, waiting on some <glossary>event<\/glossary>.\nWhen that event happens, these processes\nare called into action. Remember, it is the responsibility of the sched process\nto free memory when a process runs short of it. So, it is not until memory is\nneeded that sched starts up.\n<\/p>\n<p>\nHow does sched know that memory is needed? When a process makes reference to\na place in its <glossary>virtual memory<\/glossary> space that does not yet exist in\nphysical memory, a page <glossary>fault<\/glossary> occurs.\nFaults belong to a group of system events called\n<i>exceptions<\/i>. An exception is simply something that occurs outside of what\nis normally expected. Faults (exceptions) can occur either before or during the\nexecution of an instruction.\n<\/p>\n<p>\nFor example, if an instruction that is not yet in memory needs to be read,\nthe exception  (page fault) occurs <i>before<\/i> the instruction starts being\nexecuted. On the other hand, if the instruction is supposed to read data from a\n<glossary>virtual memory<\/glossary> location that isn&#8217;t in\n<glossary>physical memory<\/glossary>, the exception occurs <i>during<\/i> the execution\nof the instruction. In cases like these, once the\nmissing memory location is loaded into <glossary>physical memory<\/glossary>,\n the <glossary>CPU<\/glossary> can start the instruction.\n<\/p>\n<question id=\"171\" text=\"In some cases, commands which cause traps are not restarted.\" \/>\n<p>\nTraps are exceptions that occur <i>after<\/i> an instruction has been  executed.\nFor example, attempting to divide by zero generates an exception. However,\nin this case it doesn&#8217;t make sense to restart the instruction because every time we\nto try to run that instruction, it still comes up with a Divide-by-Zero exception.\nThat is, all memory  references are read before we start to execute the command.\n<\/p>\n<p>\nIt is also possible for processes to generate exceptions intentionally. These programmed\nexceptions are called <glossary>software interrupts<\/glossary>.\n<\/p>\n<p>\nWhen any one of these exceptions occurs, the system must react to the exception. To react,\nthe system will usually switch to another process to deal with the exception, which means\na <glossary>context switch<\/glossary>. In our discussion of process scheduling, I mentioned\nthat at every <glossary>clock tick<\/glossary> the priority of every process\nis recalculated. To make those calculations, something other than those\nprocesses have to run.\n<\/p>\n<p>\nIn Linux, the system timer (or clock) is programmed to generate a hardware\n<glossary>interrupt<\/glossary> 100 times a second (as defined by the HZ system parameter).\nThe <glossary>interrupt<\/glossary> is accomplished by sending a signal to a special chip\non the motherboard called an <glossary>interrupt<\/glossary> controller. (We go into more\ndetail about these in the <tutorial id=106>section on hardware<\/tutorial>.)\nThe <glossary>interrupt<\/glossary> controller then sends an interrupt to the\n<glossary>CPU<\/glossary>.\nWhen the CPU receives this <glossary>signal<\/glossary>,\n it knows that the <glossary>clock tick<\/glossary>\nhas occurred and it jumps to a special part of the <glossary>kernel<\/glossary>\nthat handles the clock <glossary>interrupt<\/glossary>. Scheduling priorities are also\nrecalculated within this same section of code.\n<\/p>\n<p>\nBecause the system might be doing something more important when the clock\ngenerates an interrupt, you can turn interrupts off using\n&#8220;masking&#8221;. In other words, there\nis a way to <i>mask out <\/i>interrupts. Interrupts that can be masked out are\ncalled <i>maskable interrupts<\/i>. An example of something more important than\nthe\nclock would be accepting input from the keyboard. This is why clock ticks are\nlost on systems with a lot of users inputting a lot of\ndata. As a result, the system clock appears to slow down over\ntime.\n<\/p>\n<question id=\"172\" text=\"An interrupt that cannot be ignored is referred to as what?\" \/>\n<p>\nSometimes events occur on the system that you want to know about <i>no matter\nwhat<\/i>. Imagine what would\nhappen if memory was bad. If the system was in the middle of writing to the hard\ndisk when it\nencountered the bad memory, the results could be disastrous. If the system\nrecognizes the bad\nmemory, the hardware generates an <glossary>interrupt<\/glossary>\nto alert the <glossary>CPU<\/glossary>. If the CPU is told to ignore all hardware\ninterrupts, it\nwould ignore this one. Instead, the hardware has the ability to generate an\n<glossary>interrupt<\/glossary>\nthat cannot be ignored, or &#8220;masked out&#8221;, called a <i>non-maskable\n<glossary>interrupt<\/glossary>.\n<\/i> Non-maskable interrupts are\ngenerically referred to as NMIs.\n<\/p>\n<p>\nWhen an <glossary>interrupt<\/glossary>\nor an exception occurs, it must be dealt\nwith to ensure the integrity of the system. How the system reacts depends on\nwhether it was an\nexception or <glossary>interrupt<\/glossary>.\n In addition, what happens when the hard disk generates an interrupt is going\nto be different than when the clock generates one.\n<\/p><p>\nWithin the\n<glossary>kernel<\/glossary>\nis the <i>Interrupt\nDescriptor Table<\/i> (IDT), which is a list of descriptors (pointers) that point\nto the functions\nthat handle the particular <glossary>interrupt<\/glossary>\nor exception. These functions are called the <i>interrupt<\/i>\nor <i>exception handlers.<\/i> When an <glossary>interrupt<\/glossary>\nor exception occurs, it has a particular value,\ncalled an identifier or vector. Table 0-2 contains a list of the defined\ninterrupt\nvectors.\n<\/p>\n<p>\nTable Interrupt Vectors\n<\/p>\n<p>\n<center>\n<table BORDER CELLSPACING=2 BORDERCOLOR=\"#000000\" CELLPADDING=7\nWIDTH=396><tr><td>\nIdentifier<\/td><td>\nDescription<\/td><\/tr><tr><td>\n0<\/td><td>Divide\nerror<\/td><\/tr><tr><td> 1<\/td><td>\nDebug exception<\/td><\/tr><tr><td>\n2<\/td><td>Non-maskable\ninterrupt<\/td><\/tr><tr><td> 3<\/td><td >\nBreakpoint<\/td><\/tr><tr><td>\n4<\/td><td>\nOverflow<\/td><\/tr><tr><td>\n5<\/td><td>Bounds\ncheck<\/td><\/tr><tr><td> 6<\/td><td>\nInvalid opcode<\/td><\/tr><tr><td>\n7<\/td><td>Coprocessor not\navailable<\/td><\/tr><tr><td> 8<\/td><td>\nDouble fault<\/td><\/tr><tr><td>\n9<\/td><td>\n(reserved)<\/td><\/tr><tr><td>\n10<\/td><td>Invalid\nTSS<\/td><\/tr><tr><td> 11<\/td><td>\nSegment not present<\/td><\/tr><tr><td>\n12<\/td><td>Stack\nexception<\/td><\/tr><tr><td> 13<\/td><td>\nGeneral protection fault<\/td><\/tr><tr><td>\n14<\/td><td>Page\nfault<\/td><\/tr><tr><td> 15<\/td><td>\n(reserved)<\/td><\/tr><tr><td>\n16<\/td><td>Coprocessor\nerror<\/td><\/tr><tr><td> 17<\/td><td>\nalignment error (80486)<\/td><\/tr><tr><td>\n18-31<\/td><td>\n(reserved)<\/td><\/tr><tr><td>\n32-255<\/td><td>External (HW)\ninterrupts<\/td><\/tr><\/table><\/center>\n<\/p>\n<p>\nThese numbers are actually indices into the <glossary>IDT<\/glossary>. When an\n<glossary>interrupt<\/glossary>,\nexception, or <glossary>trap<\/glossary> occurs, the system knows which number corresponds to that\nevent. It then uses that number as an index into the <glossary>IDT<\/glossary>,\nwhich in turn points to the appropriate area of memory for handling the\n<glossary>event<\/glossary>.\n<\/p>\n<p>\nIt is possible for devices to share interrupts; that\nis, multiple devices on the system can be (and ofter are) configured to use the same\n<glossary>interrupt<\/glossary>.\nIn fact, certain kinds of\ncomputers are designed to allow devices to share interrupts (I&#8217;ll talk about\nthem in the hardware section). If the <glossary>interrupt<\/glossary>\nnumber is an offset into a table of pointers to interrupt routines, how\ndoes the <glossary>kernel<\/glossary> know which one to call?\n<\/p>\n<question id=\"173\" text=\"Pointers to interrupt service routines are stored where?\" \/>\n<p>\nAs it turns out, there are two IDTs: one for shared interrupts and one for non-shared\ninterrupts. During a kernel rebuild (<tutorial id=\"91\">more on that later<\/tutorial>),\nthe kernel determines whether the <glossary>interrupt<\/glossary>\nis shared. If it is, it places the pointer to that interrupt\nroutine into the shared <glossary>IDT<\/glossary>.\nWhen an <glossary>interrupt<\/glossary>\nis generated, the interrupt routine for each of these\ndevices is called. It is up to the <glossary>interrupt<\/glossary>\nroutine to check whether the associated device really\ngenerated an <glossary>interrupt<\/glossary>.\n The order in which they are called is the order in which they are\nlinked.\n<\/p>\n<p>\nWhen an exception happens in <glossary>user mode<\/glossary>,\nthe process passes through a <glossary>trap<\/glossary>\ngate. At this point, the <glossary>CPU<\/glossary>\nno longer uses the process&#8217; user <glossary>stack<\/glossary>,\n but rather the system stack within that\nprocess&#8217; task structure. (each task structure has a portion set aside for the\nsystem stack.) At this point, that process is operating in system (kernel) mode; that is, at the\nhighest privilege level,\n0.\n<\/p>\n<p>\nThe <glossary>kernel<\/glossary>\ntreats interrupts very similarly to the way it treats exceptions: all the\ngeneral purpose registers are pushed onto the system <glossary>stack<\/glossary>\nand a common <glossary>interrupt<\/glossary>\nhandler is called.\nThe current <glossary>interrupt<\/glossary>\npriority is saved and the new priority is loaded. This prevents interrupts at\nlower priority levels from interrupting the <glossary>kernel<\/glossary>\nwhile it handles this <glossary>interrupt<\/glossary>. Then the real\ninterrupt handler is called.\n<\/p>\n<p>\nBecause an exception is not fatal, the process will return from\nwhence it came. It is possible that a <glossary>context switch<\/glossary>\noccurs immediately on return from <glossary>kernel<\/glossary>\nmode.\nThis might be the result of an exception with a lower priority. Because it could\nnot <glossary>interrupt<\/glossary>\nthe process in <glossary>kernel<\/glossary>\nmode, it had to wait until it returned to <glossary>user mode<\/glossary>.\n Because the exception has a\nhigher priority than the process when it is in <glossary>user mode<\/glossary>,\n a <glossary>context switch<\/glossary>\noccurs immediately after\nthe process returns to <glossary>user mode<\/glossary>.\n<\/p>\n<question id=\"170\" text=\"To ensure integrity of your data, an exception causes the kernel to 'panic'.\" \/>\n<p>\nIt is abnormal for another exception to occur while the process is in kernel\nmode. Even a page\nfault can be considered a software <glossary>event<\/glossary>.\n Because the entire <glossary>kernel<\/glossary>\nis in memory all the time, a page <glossary>fault<\/glossary>\nshould not happen. When a <glossary>page fault<\/glossary>\ndoes happen when in <glossary>kernel<\/glossary>\nmode, the kernel panics. Special routines have been built into the <glossary>kernel<\/glossary>\nto deal with the <glossary>panic<\/glossary>\nto help the system shut down as gracefully as possible. Should something else happen\nto cause another exception while the system\nis trying to <glossary>panic<\/glossary>, a double panic occurs.\n<\/p>\n<p>\nThis may sound confusing because I just said that\na <glossary>context switch<\/glossary>\ncould occur as the result of another exception. What this means is that the\nexception occurred in <glossary>user mode<\/glossary>,\n so there must be a jump to <glossary>kernel<\/glossary>\nmode. This does not mean that the\nprocess continues in <glossary>kernel<\/glossary>\nmode until it is finished. It may (depending on what it is doing) be\ncontext-switched out. If another process has run before the first one gets its\nturn on the CPU again, that process may generate the exception.\n<\/p>\n<p>\nUnlike exceptions, another <glossary>interrupt<\/glossary>\ncould possibly occur while the <glossary>kernel<\/glossary>\nis handling the first one (and therefore is in kernel mode). If the\nsecond <glossary>interrupt<\/glossary>\nhas a higher priority than the first, a <glossary>context switch<\/glossary>\nwill occur and the new\ninterrupt will be handled. If the second <glossary>interrupt<\/glossary>\nhas the same or lower priority, then the kernel\nwill &#8220;put it on hold.&#8221; These are not ignored, but rather saved (queued) to be\ndealt with later.\n<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Interrupts Exceptions and Traps Normally, processes are asleep, waiting on some event. When that event happens, these processes are called into action. Remember, it is the responsibility of the sched process to free memory when a process runs short of &hellip; <a href=\"http:\/\/www.linux-tutorial.info\/?page_id=247\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-247","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"http:\/\/www.linux-tutorial.info\/index.php?rest_route=\/wp\/v2\/pages\/247","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/www.linux-tutorial.info\/index.php?rest_route=\/wp\/v2\/pages"}],"about":[{"href":"http:\/\/www.linux-tutorial.info\/index.php?rest_route=\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"http:\/\/www.linux-tutorial.info\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.linux-tutorial.info\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=247"}],"version-history":[{"count":1,"href":"http:\/\/www.linux-tutorial.info\/index.php?rest_route=\/wp\/v2\/pages\/247\/revisions"}],"predecessor-version":[{"id":592,"href":"http:\/\/www.linux-tutorial.info\/index.php?rest_route=\/wp\/v2\/pages\/247\/revisions\/592"}],"wp:attachment":[{"href":"http:\/\/www.linux-tutorial.info\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=247"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}