亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > .NET > 正文

C標準庫源碼解剖(9):控制函數assert.h, setjmp.h和signal.h

2024-07-10 13:27:18
字體:
來源:轉載
供稿:網友

控制函數用于對C語言程序的標準控制流(如if/else、switch、for等)提供擴展,在頭文件assert.h、setjmp.h和signal.h中提供,分別提供表達式斷言功能、非本地跳轉功能、信號處理功能。
    1、assert.h: 提供用于斷言的assert宏。程序中若沒有定義NDEBUG,則asset(exp)對表達式exp進行斷言,若斷言為假(即為0),則會調用__assert_fail函數打印一條“斷言失敗”的消息,并終止程序。若定義了NDEBUG宏,則assert通常為空語句。

 

[cpp] view plaincopy
  1. /* ISO C99 Standard: 7.2 診斷  <assert.h> */  
  2. #ifdef  _ASSERT_H  
  3. # undef _ASSERT_H  
  4. # undef assert  
  5. # undef __ASSERT_VOID_CAST  
  6. # ifdef __USE_GNU  
  7. #  undef assert_perror  
  8. # endif  
  9. #endif /* assert.h  */  
  10. #define _ASSERT_H   1  
  11. #include <features.h>  
  12. #if defined __cplusplus && __GNUC_PREREQ (2,95)  
  13. # define __ASSERT_VOID_CAST static_cast<void>  
  14. #else  
  15. # define __ASSERT_VOID_CAST (void)  
  16. #endif  
  17. /* void assert (int expression); 
  18.    如果定義了NDEBUG,什么也不做,如果沒有定義,且EXPRESSION為0,則打印一個錯誤消息,然后終止程序 
  19.   */  
  20. #ifdef  NDEBUG  
  21. # define assert(expr)       (__ASSERT_VOID_CAST (0))  
  22. /* void assert_perror (int errnum); 
  23.    如果定義了NDEBUG,什么也不做。如果沒有定義,且ERRNUM為0,則打印對應于錯誤碼ERRNUM的錯誤消息, 
  24.    然后終止程序  */  
  25. # ifdef __USE_GNU  
  26. #  define assert_perror(errnum) (__ASSERT_VOID_CAST (0))  
  27. # endif  
  28. #else /* 沒有定義NDEBUG */  
  29. #ifndef _ASSERT_H_DECLS  
  30. #define _ASSERT_H_DECLS  
  31. __BEGIN_DECLS  
  32. /* 這里打印一條“斷言失敗”的消息,然后終止程序  */  
  33. extern void __assert_fail (__const char *__assertion, __const char *__file,  
  34.                unsigned int __line, __const char *__function)  
  35.      __THROW __attribute__ ((__noreturn__));  
  36. /* 與上面一樣,但打印錯誤碼ERRNUM的錯誤消息  */  
  37. extern void __assert_perror_fail (int __errnum, __const char *__file,  
  38.                   unsigned int __line,  
  39.                   __const char *__function)  
  40.      __THROW __attribute__ ((__noreturn__));  
  41.   
  42. /* 下面的函數在這里并沒有使用,但為了與標準兼容,還是需要提供  */  
  43. extern void __assert (const char *__assertion, const char *__file, int __line)  
  44.      __THROW __attribute__ ((__noreturn__));  
  45.   
  46. __END_DECLS  
  47. #endif /* Not _ASSERT_H_DECLS */  
  48. /* 使用上面的函數來定義完整的assert宏 */  
  49. # define assert(expr)                           /  
  50.   ((expr)                               /  
  51.    ? __ASSERT_VOID_CAST (0)                     /  
  52.    : __assert_fail (__STRING(expr), __FILE__, __LINE__, __ASSERT_FUNCTION))  
  53. # ifdef __USE_GNU  
  54. #  define assert_perror(errnum)                     /  
  55.   (!(errnum)                                /  
  56.    ? __ASSERT_VOID_CAST (0)                     /  
  57.    : __assert_perror_fail ((errnum), __FILE__, __LINE__, __ASSERT_FUNCTION))  
  58. # endif  
  59. /* 2.4及之后版本的GCC定義了一個魔術變量__PRETTY_FUNCTION__,它包含當前定義的函數名,這在2.6版本之前 
  60.    的G++中打破了。C9x有一個類似的名為__func__的變量,但首選的是GCC的這個變量,因為它重新覆蓋了C++中的 
  61.    這個函數名 */  
  62. # if defined __cplusplus ? __GNUC_PREREQ (2, 6) : __GNUC_PREREQ (2, 4)  
  63. #   define __ASSERT_FUNCTION    __PRETTY_FUNCTION__  
  64. # else  
  65. #  if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L  
  66. #   define __ASSERT_FUNCTION    __func__  
  67. #  else  
  68. #   define __ASSERT_FUNCTION    ((__const char *) 0)  
  69. #  endif  
  70. # endif  
  71. #endif /* NDEBUG.  */  

 

 

[cpp] view plaincopy
  1. /* assert.c:assert功能的實現,核心的函數為__assert_fail  */  
  2. #include <assert.h>  
  3. #include <libintl.h>  
  4. #include <stdio.h>  
  5. #include <stdlib.h>  
  6. #include <sysdep.h>  
  7. #include <unistd.h>  
  8.   
  9. extern const char *__progname;  
  10. #ifdef USE_IN_LIBIO  
  11. # include <wchar.h>  
  12. # include <libio/iolibio.h>  
  13. # define fflush(s) INTUSE(_IO_fflush) (s)  
  14. #endif  
  15. /* 本函數當傳遞一個包含斷言表達式的字符串、一個文件名、和一個行號時,在標準 
  16.     錯誤流上用以下格式打印一條消息: 
  17.     a.c:10: foobar: Assertion `a == b' failed. 
  18.     然后通過調用abort來終止程序的執行 */  
  19. #ifdef FATAL_PREPARE_INCLUDE  
  20. # include FATAL_PREPARE_INCLUDE  
  21. #endif  
  22. #undef __assert_fail  
  23. void  
  24. __assert_fail (const char *assertion, const char *file, unsigned int line,  
  25.            const char *function)  
  26. {  
  27.   char *buf;  
  28. #ifdef FATAL_PREPARE  
  29.   FATAL_PREPARE;  
  30. #endif  
  31.   /* 把指定格式的消息寫入到buf中 */  
  32.   if (__asprintf (&buf, _("%s%s%s:%u: %s%sAssertion `%s' failed./n"),  
  33.           __progname, __progname[0] ? ": " : "",  
  34.           file, line,  
  35.           function ? function : "", function ? ": " : "",  
  36.           assertion) >= 0)  
  37.     {  
  38.       (void) __fxprintf (NULL, "%s", buf);    /* 打印buf中的消息  */  
  39.       (void) fflush (stderr);   /* 刷新標準錯誤流的狀態(注意stderr并不緩沖) */   
  40.       /* 我們要釋放消息緩沖區,因為應用程序可能會捕捉到SIGABRT信號 */  
  41.       free (buf);  
  42.     }  
  43.   else  /* 消息寫入未成功 */  
  44.     {  
  45.       /* 至少要打印一個最小的消息  */  
  46.       static const char errstr[] = "Unexpected error./n";  
  47.       __libc_write (STDERR_FILENO, errstr, sizeof (errstr) - 1);  
  48.     }  
  49.   abort ();  /* 調用abort終止程序 */  
  50. }  
  51. hidden_def(__assert_fail)  

 

 

[cpp] view plaincopy
  1. /* assert-perr.c:assert_perror功能是GNU的一個擴展,核心的函數是__assert_perror_fail */  
  2. #include <assert.h>  
  3. #include <libintl.h>  
  4. #include <stdio.h>  
  5. #include <stdlib.h>  
  6. #include <string.h>  
  7. #include <sysdep.h>  
  8. #include <unistd.h>  
  9.   
  10. extern const char *__progname;  
  11. #ifdef USE_IN_LIBIO  
  12. # include <wchar.h>  
  13. # include <libio/iolibio.h>  
  14. # define fflush(s) INTUSE(_IO_fflush) (s)  
  15. #endif  
  16. /* 本函數當傳遞一個包含斷言表達式的字符串、一個文件名、和一個行號時,在標準 
  17.     錯誤流上用以下格式打印一條消息: 
  18.     a.c:10: foobar: Unexpected error: Computer bought the farm 
  19.     然后通過調用abort來終止程序的執行  */  
  20. #ifdef FATAL_PREPARE_INCLUDE  
  21. # include FATAL_PREPARE_INCLUDE  
  22. #endif  
  23. void  
  24. __assert_perror_fail (int errnum,  
  25.               const char *file, unsigned int line,  
  26.               const char *function)  
  27. {  
  28.   char errbuf[1024];  
  29.   char *buf;  
  30. #ifdef FATAL_PREPARE  
  31.   FATAL_PREPARE;  
  32. #endif  
  33.   /* 把指定格式的消息寫入到buf中 */  
  34.   if (__asprintf (&buf, _("%s%s%s:%u: %s%sUnexpected error: %s./n"),  
  35.           __progname, __progname[0] ? ": " : "",  
  36.           file, line,  
  37.           function ? function : "", function ? ": " : "",  
  38.           __strerror_r (errnum, errbuf, sizeof errbuf)) >= 0)  
  39.     {  
  40.       (void) __fxprintf (NULL, "%s", buf);    /* 打印buf中的消息  */  
  41.       (void) fflush (stderr);  /* 刷新標準錯誤流的狀態(注意stderr并不緩沖) */  
  42.       /* 我們要釋放消息緩沖區,因為應用程序可能會捕捉到SIGABRT信號 */  
  43.       free (buf);  
  44.     }  
  45.   else  /* 消息寫入未成功 */  
  46.     {  
  47.       /* 至少要打印一個最小的消息  */  
  48.       static const char errstr[] = "Unexpected error./n";  
  49.       __libc_write (STDERR_FILENO, errstr, sizeof (errstr) - 1);  
  50.     }  
  51.   abort ();  /* 調用abort終止程序 */  
  52. }  
  53. libc_hidden_def (__assert_perror_fail)  

 

 

[cpp] view plaincopy
  1. /* __assert.c:__assert函數的實現 */  
  2. /* 我們必須參看原型:沒有定義NDEBUG時才會在<assert.h>有__assert的原型  */  
  3. #undef NDEBUG  
  4. #include <assert.h>  
  5. /* 提供__assert函數是為了與標準兼容,它的功能由__assert_fail取代 */  
  6. void  
  7. __assert (const char *assertion, const char *file, int line)  
  8. {  
  9.   __assert_fail (assertion, file, line, (const char *) 0);  
  10. }  

 

    解釋:
    (1)GNU還提供了一個擴展assert_perror,功能與assert類似,只不過打印指定的錯誤碼對應的消息,通過__assert_perror_fail函數來實現。另外提供的_assert函數是為了與標準兼容,它的功能由__assert_fail取代。
    (2)__assert_fail和__assert_perror_fail函數都是把指定格式的消息寫入到buf中,然后打印buf中的消息,并刷新標準錯誤流的狀態,釋放消息緩沖區buf,最后要調用abort函數終止程序。
    2、setjmp.h: 標準庫函數setjmp和longjmp實現基本形式的非本地跳轉。setjmp用于保存調用者的堆棧環境(被保存在表示跳轉緩沖區的jmp_buf型數組ENV中),然后返回0。longjmp用于跳轉到保存堆棧環境的地方,并從那里的setjmp調用返回,返回指定的狀態碼,如果狀態碼為0則返回1。

 

[cpp] view plaincopy
  1. /* ISO C99 Standard: 7.13 非本地跳轉 <setjmp.h> */  
  2. #ifndef _SETJMP_H  
  3. #define _SETJMP_H   1  
  4. #include <features.h>  
  5. __BEGIN_DECLS  
  6. #include <bits/setjmp.h>      /* 獲取__jmp_buf  */  
  7. #include <bits/sigset.h>      /* 獲取__sigset_t  */  
  8.   
  9. /* 調用環境,可能還會附加一個被保存的信號掩碼  */  
  10. struct __jmp_buf_tag  
  11.   {  
  12.     /* 注意:依賴于機器的__sigsetjmp定義假定一個jmp_buf從__jmp_buf開始,后面緊跟著 
  13.         __mask_was_saved。不要移動這些成員或者在前面添加其他的成員 */  
  14.     __jmp_buf __jmpbuf;     /* 調用環境  */  
  15.     int __mask_was_saved;   /* 保存信號掩碼嗎?  */  
  16.     __sigset_t __saved_mask;    /* 被保存的信號掩碼  */  
  17.   };  
  18.   
  19. __BEGIN_NAMESPACE_STD  
  20. typedef struct __jmp_buf_tag jmp_buf[1];  /* 定義jmp_buf數組 */  
  21. /* 在ENV中保存調用環境,同時也會保存信號掩碼,返回0 */  
  22. extern int setjmp (jmp_buf __env) __THROW;  
  23. __END_NAMESPACE_STD  
  24. /* 在ENV中保存調用環境,如果SAVEMASK不為零,則同時也會保存信號掩碼。返回0。 
  25.     這是sigsetjmp函數的內部名稱 */  
  26. extern int __sigsetjmp (struct __jmp_buf_tag __env[1], int __savemask) __THROW;  
  27. #ifndef __FAVOR_BSD  
  28. /* 在ENV中保存調用環境,不保存信號掩碼。返回0 */  
  29. extern int _setjmp (struct __jmp_buf_tag __env[1]) __THROW;  
  30. /* 不保存信號掩碼。這與BSD函數'_setjmp'等價 */  
  31. # define setjmp(env)    _setjmp (env)  
  32. #else  
  33. /* 在4.3 BSD兼容模式下,setjmp像sigsetjmp(ENV,1)一樣來保存信號掩碼。我們 
  34.     必須定義一個宏,因為ISO C指出setjmp是完整的 */  
  35. # define setjmp(env)    setjmp (env)  
  36. #endif /* Favor BSD.  */  
  37.   
  38. __BEGIN_NAMESPACE_STD  
  39. /* 跳轉到保存在ENV中的環境處,使那里的setjmp調用返回VAL,或者返回1(如果VAL為0) */  
  40. extern void longjmp (struct __jmp_buf_tag __env[1], int __val)  
  41.      __THROW __attribute__ ((__noreturn__));  
  42. __END_NAMESPACE_STD  
  43. #if defined __USE_BSD || defined __USE_XOPEN  
  44. /* 與上面相同。通常_longjmp與setjmp一起使用,不保存信號掩碼。但怎樣保存ENV決定了longjmp 
  45.     是否恢復掩碼;而_longjmp只是一個別名 */  
  46. extern void _longjmp (struct __jmp_buf_tag __env[1], int __val)  
  47.      __THROW __attribute__ ((__noreturn__));  
  48. #endif  
  49.   
  50. #ifdef  __USE_POSIX  
  51. /* 對jmp_buf和sigjmp_buf使用同樣的類型。__mask_was_saved標志決定 
  52.     longjmp是否將恢復信號掩碼 */  
  53. typedef struct __jmp_buf_tag sigjmp_buf[1];  
  54. /* 在ENV中保存調用環境,同時也會保存信號掩碼(如果SAVEMASK不為零),返回0  */  
  55. # define sigsetjmp(env, savemask)   __sigsetjmp (env, savemask)  
  56. /* 跳轉到保存在ENV中的環境處,使那里的sigsetjmp調用返回VAL,或者返回(如果VAL為0) 
  57.     恢復信號掩碼(如果那個sigsetjmp保存了它的話)。本函數只是longjmp的一個別名 */  
  58. extern void siglongjmp (sigjmp_buf __env, int __val)  
  59.      __THROW __attribute__ ((__noreturn__));  
  60. #endif /* Use POSIX.  */  
  61. __END_DECLS  
  62. #endif /* setjmp.h  */  

 

 

[cpp] view plaincopy
  1. /* setjmp.c:setjmp函數的實現  */  
  2. #include <errno.h>  
  3. #include <setjmp.h>  
  4. /* 在ENV中人嘎當前程序的位置,然后返回0  */  
  5. int  
  6. __libc_sigsetjmp (jmp_buf env, int savemask)  
  7. {  
  8.   /* 如果被請求的話,保存信號掩碼  */  
  9.   __sigjmp_save (env, savemask);  
  10.   __set_errno (ENOSYS);  
  11.   /* 沒有信號失敗 */  
  12.   return 0;  
  13. }  
  14. weak_alias (__libc_sigsetjmp, __sigsetjmp)  
  15. stub_warning (__sigsetjmp)  
  16. #include <stub-tag.h>  

 

 

[cpp] view plaincopy
  1. /* longjmp.c:longjmp函數的實現 */  
  2. #include <stddef.h>  
  3. #include <setjmp.h>  
  4. #include <signal.h>  
  5. /* 在ENV中的相應成員上設置信號掩碼,并且跳轉到ENV指定的位置處,導致那里的 
  6.     setjmp調用返回VAL,或者返回1(如果VAL為0) */  
  7. void  
  8. __libc_siglongjmp (sigjmp_buf env, int val)  
  9. {  
  10.   /* 在展開的堆棧結構上需要做清理工作  */  
  11.   _longjmp_unwind (env, val);  
  12.   if (env[0].__mask_was_saved)  
  13.     /* 恢復被保存的掩碼  */  
  14.     (void) __sigprocmask (SIG_SETMASK, &env[0].__saved_mask,  
  15.               (sigset_t *) NULL);  
  16.   /* 調用依賴于機器的函數來恢復機器狀態  */  
  17.   __longjmp (env[0].__jmpbuf, val ?: 1);  
  18. }  
  19. strong_alias (__libc_siglongjmp, __libc_longjmp)  
  20. libc_hidden_def (__libc_longjmp)  
  21. weak_alias (__libc_siglongjmp, _longjmp)  
  22. weak_alias (__libc_siglongjmp, longjmp)  
  23. weak_alias (__libc_siglongjmp, siglongjmp)  

 

    注意setjmp和longjmp函數都是直接調用內部函數來完成工作的。頭文件setjmp.h中的其他部分都是BSD、XOPEN或POSIX方面的擴展。
    3、signal.h: 定義了信號原子類型sig_atomic_t、信號處理函數的注冊signal、發送信號的函數raise。它包含了bits/signum.h,這個Linux系統的頭文件中定義了C標準中的信號及其他一些信號。標準C語言中的信號有SIGINT,SIGILL,SIGABRT,SIGFPE,SIGSEGV,SIGTERM,還要3個特殊的信號SIGERR,SIG_DFL, SIG_IGN,因此標準C語言中總共有9個信號。

    signal.h代碼如下:

 

[cpp] view plaincopy
  1. /* ISO C99 Standard: 7.14 信號處理 <signal.h> */  
  2. #ifndef _SIGNAL_H  
  3. #if !defined __need_sig_atomic_t && !defined __need_sigset_t  
  4. # define _SIGNAL_H  
  5. #endif  
  6. #include <features.h>  /* 定義了一些編譯選項 */  
  7. __BEGIN_DECLS  
  8. #include <bits/sigset.h>      /* 獲取__sigset_t和__sig_atomic_t類型  */  
  9. /* 一個可以自動修改的內部類型,它不可能是一個到達運算中間的信號 */  
  10. #if defined __need_sig_atomic_t || defined _SIGNAL_H  
  11. # ifndef __sig_atomic_t_defined  
  12. #  define __sig_atomic_t_defined  
  13. __BEGIN_NAMESPACE_STD  
  14. typedef __sig_atomic_t sig_atomic_t;  /* 定義信號原子類型 */  
  15. __END_NAMESPACE_STD  
  16. # endif  
  17. # undef __need_sig_atomic_t  
  18. #endif  
  19. #if defined __need_sigset_t || (defined _SIGNAL_H && defined __USE_POSIX)  
  20. # ifndef __sigset_t_defined  
  21. #  define __sigset_t_defined  
  22. typedef __sigset_t sigset_t;  /* 信號集類型 */  
  23. # endif  
  24. # undef __need_sigset_t  
  25. #endif  
  26. #ifdef _SIGNAL_H  
  27. #include <bits/types.h>   /* 定義了一些擴展整數類型 */  
  28. #include <bits/signum.h>  /* 定義了C標準中的信號及其他一些信號 */  
  29. #if defined __USE_XOPEN || defined __USE_XOPEN2K  
  30. # ifndef __pid_t_defined  
  31. typedef __pid_t pid_t;  /* 進程ID類型 */  
  32. #  define __pid_t_defined  
  33. #endif  
  34. #ifdef __USE_XOPEN  
  35. # endif  
  36. # ifndef __uid_t_defined  
  37. typedef __uid_t uid_t;  /* 用戶ID類型 */  
  38. #  define __uid_t_defined  
  39. # endif  
  40. #endif  /* Unix98 */  
  41.   
  42. /* 信號處理函數類型  */  
  43. typedef void (*__sighandler_t) (int);  
  44. /* X/Open的signal定義指定SVID的語義。當需要X/Open兼容性時使用另外一個函數sysv_signal */  
  45. extern __sighandler_t __sysv_signal (int __sig, __sighandler_t __handler)  
  46.      __THROW;  
  47. #ifdef __USE_GNU  
  48. extern __sighandler_t sysv_signal (int __sig, __sighandler_t __handler)  
  49.      __THROW;  
  50. #endif  
  51. /* 為信號SIG設置信號處理函數HANDLER,返回原來的信號處理函數,出錯則返回SIG_ERR 
  52.     默認情況下signal擁有BSD風格的語義 */  
  53. __BEGIN_NAMESPACE_STD  
  54. #ifdef __USE_BSD  
  55. extern __sighandler_t signal (int __sig, __sighandler_t __handler)  
  56.      __THROW;  
  57. #else  
  58. /* 確保使用的signal實現是SVID的版本 */  
  59. # ifdef __REDIRECT_NTH  
  60. extern __sighandler_t __REDIRECT_NTH (signal,  
  61.                       (int __sig, __sighandler_t __handler),  
  62.                       __sysv_signal);  
  63. # else  
  64. #  define signal __sysv_signal  
  65. # endif  
  66. #endif  
  67. __END_NAMESPACE_STD  
  68. #ifdef __USE_XOPEN  
  69. /* X/Open的signal定義與BSD的版本有沖突,因此它們定義定義另外一個函數bsd_singnal */  
  70. extern __sighandler_t bsd_signal (int __sig, __sighandler_t __handler)  
  71.      __THROW;  
  72. #endif  
  73. /* 發送信號SIG給PID表示的這個進程。如果PID為0,則發送信號SIG給當前進程組的所有進程。 
  74.     如果PID<-1,則發送SIG給PID表示的進程組中的所有進程 */  
  75. #ifdef __USE_POSIX  
  76. extern int kill (__pid_t __pid, int __sig) __THROW;  
  77. #endif /* Use POSIX.  */  
  78. #if defined __USE_BSD || defined __USE_XOPEN_EXTENDED  
  79. /* 發送信號SIG給進程組PGRP中的所有進程。如果PGRP為0,則發送信號SIG給 
  80.     當前進程組的所有進程 */  
  81. extern int killpg (__pid_t __pgrp, int __sig) __THROW;  
  82. #endif /* Use BSD || X/Open Unix.  */  
  83. __BEGIN_NAMESPACE_STD  
  84. /* 發送信號SIG。例如,發送SIG給你自己  */  
  85. extern int raise (int __sig) __THROW;  
  86. __END_NAMESPACE_STD  
  87. /* 下面都是一些擴展或內部函數 */  
  88. #endif /* signal.h  */  
  89. __END_DECLS  
  90. #endif /* not signal.h */  

 

    bits/signum.h代碼如下:

 

[cpp] view plaincopy
  1. /* bits/signum.h:信號碼定義,Linux版本  */  
  2. #ifdef  _SIGNAL_H  
  3. /* 偽信號函數  */  
  4. #define SIG_ERR ((__sighandler_t) -1)       /* 出錯時返回  */  
  5. #define SIG_DFL ((__sighandler_t) 0)        /* 默認行為  */  
  6. #define SIG_IGN ((__sighandler_t) 1)        /* 忽略信號  */  
  7. #ifdef __USE_UNIX98  
  8. # define SIG_HOLD   ((__sighandler_t) 2)    /* 給信號加保留的掩碼  */  
  9. #endif  
  10.   
  11. /* 信號  */  
  12. #define SIGHUP      1   /* 掛斷 (POSIX).  */  
  13. #define SIGINT      2   /* 中斷 (ANSI).  */  
  14. #define SIGQUIT     3   /* 退出 (POSIX).  */  
  15. #define SIGILL      4   /* 非法指令 (ANSI).  */  
  16. #define SIGTRAP     5   /* 跟蹤捕捉 (POSIX).  */  
  17. #define SIGABRT     6   /* 異常終止,如調用abort (ANSI).  */  
  18. #define SIGIOT      6   /* 圖像輸出終端(IOT)陷阱 (4.2 BSD).  */  
  19. #define SIGBUS      7   /* 總線錯誤 (4.2 BSD).  */  
  20. #define SIGFPE      8   /* 浮點數異常 (ANSI).  */  
  21. #define SIGKILL     9   /* 殺死,此信號可解鎖 (POSIX).  */  
  22. #define SIGUSR1     10  /* 用戶定義信號1 (POSIX).  */  
  23. #define SIGSEGV     11  /* 段錯誤,即無效內存訪問 (ANSI).  */  
  24. #define SIGUSR2     12  /* 用戶定義信號2 (POSIX).  */  
  25. #define SIGPIPE     13  /* 管道錯誤 (POSIX).  */  
  26. #define SIGALRM     14  /* 時鐘警告 (POSIX).  */  
  27. #define SIGTERM     15  /* 終止 (ANSI).  */  
  28. #define SIGSTKFLT   16  /* 堆棧故障  */  
  29. #define SIGCLD      SIGCHLD /* 等同于SIGCHLD (System V).  */  
  30. #define SIGCHLD     17  /* 子進程狀態已經改變 (POSIX).  */  
  31. #define SIGCONT     18  /* 繼續 (POSIX).  */  
  32. #define SIGSTOP     19  /* 停止,此信號可解鎖 (POSIX).  */  
  33. #define SIGTSTP     20  /* 鍵盤發的停止信號 (POSIX).  */  
  34. #define SIGTTIN     21  /* 從tty進行后臺讀操作 (POSIX).  */  
  35. #define SIGTTOU     22  /* 后臺寫入tty (POSIX).  */  
  36. #define SIGURG      23  /* socket緊急狀態 (4.2 BSD).  */  
  37. #define SIGXCPU     24  /* 超出CPU限制 (4.2 BSD).  */  
  38. #define SIGXFSZ     25  /* 超出文件大小限制 (4.2 BSD).  */  
  39. #define SIGVTALRM   26  /* 時鐘虛擬警告 (4.2 BSD).  */  
  40. #define SIGPROF     27  /* 時鐘Profiling警告 (4.2 BSD).  */  
  41. #define SIGWINCH    28  /* 窗口大小改變 (4.3 BSD, Sun).  */  
  42. #define SIGPOLL     SIGIO   /* 可移植的事件發生 (System V).  */  
  43. #define SIGIO       29  /* 可以執行I/O (4.2 BSD).  */  
  44. #define SIGPWR      30  /* 重啟時電源失效 (System V).  */  
  45. #define SIGSYS      31  /* 錯誤的系統調用  */  
  46. #define SIGUNUSED   31  
  47. #define _NSIG       65  /* 最大的信號值+1(包括實時信號)  */  
  48. #define SIGRTMIN        (__libc_current_sigrtmin ())  
  49. #define SIGRTMAX        (__libc_current_sigrtmax ())  
  50. /* 這些是內核的硬限制。這些值不應該在用戶級別使用 */  
  51. #define __SIGRTMIN  32  
  52. #define __SIGRTMAX  (_NSIG - 1)  
  53. #endif  /* <signal.h> included.  */  

 

    signal函數和raise函數的實現:

 

[cpp] view plaincopy
  1. /* signal.c:signal函數的實現  */  
  2. #include <errno.h>  
  3. #include <signal.h>  
  4. /* 為信號SIG設置信號處理函數HANDLER,返回原來的信號處理函數,出錯則返回SIG_ERR  */  
  5. __sighandler_t  
  6. signal (sig, handler)  
  7.      int sig;  
  8.      __sighandler_t handler;  
  9. {  
  10.   __set_errno (ENOSYS);  
  11.   return SIG_ERR;  
  12. }  
  13. weak_alias (signal, ssignal)  
  14. stub_warning (signal)  
  15. stub_warning (ssignal)  
  16. #include <stub-tag.h>  

 

 

[cpp] view plaincopy
  1. /* raise.c:raise函數的實現  */  
  2. #include <signal.h>  
  3. #include <errno.h>  
  4. /* 發送SIG  */  
  5. int  
  6. raise (sig)  
  7.      int sig;  
  8. {  
  9.   __set_errno (ENOSYS);  
  10.   return -1;  
  11. }  
  12. weak_alias (raise, gsignal)  
  13. stub_warning (raise)  
  14. stub_warning (gsignal)  
  15. #include <stub-tag.h>  

 

    注意signal和raise函數并沒有做任何特別的實現,只是處理了一下出錯時的情況(返回SIG_ERR,即-1)。真正的實現使用Linux中有對應功能的函數,signal直接映射到Linux的ssignal函數,raise直接映射到Linux的gsignal函數。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
日本精品久久久| 久久精品国产亚洲一区二区| 亚洲人成电影网站色xx| 久久久999精品| 成人性生交xxxxx网站| 国产视频精品xxxx| 欧美大片免费观看在线观看网站推荐| 欧美高清视频在线播放| 国产亚洲精品高潮| 亚洲色图偷窥自拍| 成人网页在线免费观看| 午夜欧美大片免费观看| 日韩在线资源网| 国产精品福利在线观看| 97久久超碰福利国产精品…| 亚洲新声在线观看| 日本三级久久久| 国产精品91久久久| 欧美日韩爱爱视频| 91精品国产综合久久久久久久久| 69久久夜色精品国产7777| 国产精品∨欧美精品v日韩精品| 日韩精品视频观看| 国产亚洲人成网站在线观看| 亚洲欧洲激情在线| 亚洲free性xxxx护士白浆| 亚洲深夜福利网站| 亚洲精品永久免费| 国产精品影片在线观看| 亚洲一区二区三区毛片| 亚洲第一中文字幕在线观看| 久久久久久久久国产| 国产精品视频白浆免费视频| 日韩美女视频在线观看| 亚洲第一中文字幕| www欧美日韩| 亚洲白拍色综合图区| 最新国产精品拍自在线播放| 一区二区三区在线播放欧美| 亚洲色图狂野欧美| 欧美韩国理论所午夜片917电影| 亲爱的老师9免费观看全集电视剧| 国产成人精品电影久久久| 日韩成人在线播放| 色偷偷88888欧美精品久久久| 亚洲无亚洲人成网站77777| 亚洲美女精品久久| 2019国产精品自在线拍国产不卡| 性欧美亚洲xxxx乳在线观看| 欧美亚洲第一区| 国产精品xxx视频| 成人做爰www免费看视频网站| 日本韩国欧美精品大片卡二| 日韩av在线不卡| 久久精品国产69国产精品亚洲| 国产日韩欧美一二三区| 久久精品国产亚洲精品2020| 黑人精品xxx一区一二区| 国产免费一区二区三区香蕉精| 97免费在线视频| 国产成人精品久久二区二区91| 亚洲一区第一页| 九九九久久国产免费| 97色在线视频观看| 亚洲综合色av| 日韩视频精品在线| 69av在线播放| 国模精品一区二区三区色天香| 91夜夜未满十八勿入爽爽影院| 精品久久久久久久大神国产| 久久久久久久久久亚洲| 久久久久www| 正在播放亚洲1区| 少妇激情综合网| 国产精品扒开腿做爽爽爽视频| 91精品久久久久久久久久久久久| 亚洲午夜久久久影院| 清纯唯美亚洲激情| 久久精品视频免费播放| 日韩在线观看成人| 日韩欧美在线观看| 91探花福利精品国产自产在线| 色婷婷av一区二区三区在线观看| 欧美大片在线免费观看| 日韩电影视频免费| 这里只有精品在线观看| 亚洲第一综合天堂另类专| 亚洲精品国产综合区久久久久久久| 精品无码久久久久久国产| 亚洲网站在线播放| 午夜剧场成人观在线视频免费观看| 一区二区三区国产视频| www.色综合| 日韩**中文字幕毛片| 日韩av黄色在线观看| 欧美日韩第一页| 国产精品999| 成人国产精品一区二区| 最近日韩中文字幕中文| 高清欧美性猛交xxxx黑人猛交| 欧美放荡办公室videos4k| 日韩福利伦理影院免费| 日韩电影中文 亚洲精品乱码| 国产成人av网址| 久久躁日日躁aaaaxxxx| 久久综合伊人77777蜜臀| 欧美黄色免费网站| 久久久www成人免费精品| 亚洲精品动漫久久久久| 日韩在线观看免费全集电视剧网站| 91夜夜未满十八勿入爽爽影院| 日韩av免费看| 国内免费精品永久在线视频| 在线精品播放av| 亚洲成人精品av| 日韩视频第一页| 国产成人短视频| 成人黄色午夜影院| 亚洲精品在线观看www| 中文字幕欧美日韩| 揄拍成人国产精品视频| 久久成人亚洲精品| 中文字幕日韩av综合精品| 亚洲无限av看| 日韩性xxxx爱| 国产精品永久免费在线| 国产婷婷成人久久av免费高清| 亲爱的老师9免费观看全集电视剧| 亚洲精品99999| 精品欧美aⅴ在线网站| 日本久久精品视频| 一区二区欧美日韩视频| 国产狼人综合免费视频| 国产97在线观看| 操人视频在线观看欧美| 色综合天天综合网国产成人网| 亚洲精品一区在线观看香蕉| 欧美日韩亚洲视频| 久久免费视频这里只有精品| 成人乱色短篇合集| 88xx成人精品| 色综合视频一区中文字幕| 国产在线视频一区| 亚洲网在线观看| 亚洲成人av在线| 欧美激情在线视频二区| 国产精品99久久久久久白浆小说| 日韩高清免费观看| 国产精品日韩在线观看| 色婷婷久久一区二区| 黑人巨大精品欧美一区二区一视频| 亚洲欧美综合另类中字| 国产精品高潮粉嫩av| 日本国产一区二区三区| 欧美成在线视频| 91精品视频免费看| 久久影院在线观看| 在线视频一区二区| 精品国产一区二区三区久久狼5月| 精品久久久精品| 在线观看日韩欧美| 国产欧美一区二区三区久久人妖| 国产精品久久久久久久久粉嫩av| 青青a在线精品免费观看|