当前位置: 首页 > news >正文

阿里云做网站需要些什么白山市住房和城乡建设局网站

阿里云做网站需要些什么,白山市住房和城乡建设局网站,深圳家装网站建设多少钱,wordpress打造官网信号 信号和信号量并没有什么关系 信号是 Linux 系统提供的一种向指定进程发生特定事件的方式#xff0c;进程要对信号做识别和处理 信号的产生是异步的 信号的产生方式 kill 命令#xff1a;kill 命令可以向进程发送指定信号kill -2 10000就是对 10000 进程发送 2 号信…信号 信号和信号量并没有什么关系 信号是 Linux 系统提供的一种向指定进程发生特定事件的方式进程要对信号做识别和处理 信号的产生是异步的 信号的产生方式 kill 命令kill 命令可以向进程发送指定信号kill -2 10000就是对 10000 进程发送 2 号信号9 号信号不能进行自定义处理因此使用kill -9还是会退出键盘键盘可以发送信号ctrlc发送的是 2 号信号SIGINTctrl\发送的是 3 号信号SIGQUIT系统调用系统调用kill原型int kill(pid_t pid, int sig);向指定的进程发送任意信号成功返回 0失败返回-1 signal 函数 signal(signalfunc)//接收signal信号若收到了signal表示的信号则执行func函数 //只需捕捉一次后续一直有效kill系统调用 int kill(pid,signum)//向指定进程发送指定的信号raise系统调用 int raise(sig)//向自己发送指定的信号等价于kill(getpid(),sig) signal本质是一个异步事件处理机制当程序在正常执行主流程代码时信号处理函数是处于等待状态的。一旦有对应的信号产生操作系统会中断当前正在执行的程序指令流转而执行信号处理函数。这个过程类似于硬件中断的处理方式 为了防止进程将所有的信号都自定义处理而导致无法被关闭因此有一些信号无法被捕捉如 9 号信号 软件条件管道、闹钟 管道读关闭写进行就会触发 SIGPIPE 闹钟 alarm() 设置闹钟当到达设定的事件后发送SIGALRM信号 int nalarm(0)表示取消闹钟,返回值表示上一个闹钟的剩余时间 int nalarm(5);表示重新设置闹钟返回值为上一个闹钟的剩余时间 闹钟设置之后默认只触发一次 闹钟信号是alarm通知OS发送的也是OS通知进程进行接收的 OS 管理闹钟的方式 将 alarm 先描述再组织alarm 结构体中有一个 expired未来的超时时间secondnow()将所有的闹钟放入一个最小堆只要堆顶的元素没有超时则全部的闹钟都没有超时 异常非法访问、操作时操作系统会给进程发送信号使进程终止 core、term 都是异常终止进程但 core 会生成一个类似于 debug 文件的文件但一般生成文件一般是被关闭的使用 ulimit -a 可以查看当前所有可用资源的限制 使用 ulimit -c 可以更改 core file 的文件大小 出现 core 异常时操作系统会将出现异常的资源从内存中移动到磁盘上这就是 core 文件 发送信号本质上就是修改 PCB 中信号的指定位图这个过程是内核进行的 可以通过kill -l查看当前所有的信号 1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1 11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM 16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP 21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ 26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR 31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN1 36) SIGRTMIN2 37) SIGRTMIN3 38) SIGRTMIN4 39) SIGRTMIN5 40) SIGRTMIN6 41) SIGRTMIN7 42) SIGRTMIN8 43) SIGRTMIN9 44) SIGRTMIN10 45) SIGRTMIN11 46) SIGRTMIN12 47) SIGRTMIN13 48) SIGRTMIN14 49) SIGRTMIN15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12 53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7 58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2 63) SIGRTMAX-1 64) SIGRTMAX 异常当除 0 或者访问野指针时导致操作系统会给进程发送信号进而造成进程崩溃除 0 会发送SIGFPE 信号非法访问野指针会发送 SIGSEGV因为这些信号默认就是终止进程因此就会导致进程退出可以通过自己接收信号来进行处理 CPU 得知运算是正常还是异常的方式CPU 内部有一个寄存器用于接收运算的结果这个寄存器里面有一个溢出标志位当这个标志位为 0 说明没有溢出也就不会发生异常一旦置为 1说明发生了溢出进而发送信号进程退出之后就释放了进程的上下文数据也就将异常的数据删除了因此推荐终止进程被信号终止的进程会有一个 core dump 标志位而正常终止的进程没有 core 和 term 这两个都是异常终止但是 core 终止会将进程终止那个时刻的镜像数据核心转储到磁盘上生成一个 debug 文件但是这个功能是默认关闭的使用ulimit -a查看核心转储功能是否打开通过使用 ulimit -c 文件大小来打开核心转储并决定核心转储的文件最大的大小由于运行在云服务器上的服务可能终止后需要立刻开启而开启后可能又会崩溃又会生成 core 文件这就可能导致硬盘空间被这些文件占满可以使用echo ./core.%e.%p | sudo tee /proc/sys/kernel/core_pattern改变生成 core 文件的位置%e 是程序名%p 是进程号可以选择不加这样就只会生成一个 core 文件也可以将kernel.core_pattern /tmp/core.%e.%p写入/etc/sysctl.conf文件然后使用sudo sysctl -p命令令配置生效 可以使用 gdb 对这个文件进行调试在 gdb 中输入对这个 core 文件进行调试core-file 文件名 阻塞信号 实际执行信号的处理动作称为信号递达(Delivery)信号从产生到递达之间的状态,称为信号未决(Pending)进程可以选择阻塞 (Block )某个信号被阻塞的信号产生时将保持在未决状态直到进程解除对此信号的阻塞才执行递达的动作阻塞和忽略是不同的只要信号被阻塞就不会递达而忽略是在递达之后可选的一种处理动作 每个信号都有两个标志位分别表示阻塞(block)和未决(pending),还有一个函数指针表示处理动作 pending 中通过位图中比特位的位置来代表信号的编号比特位的内容来代表信号是否收到 block 中通过位图中比特位的位置代表信号的编号比特位的内容代表信号是否阻塞 handler 是一个函数指针数组用于存储处理信号的方法每一个信号的编号相当于这个数组的下标通过信号的编号来找到对应的处理方法 要处理一个信号首先要 pending 为 1表示信号已经收到block 为 0表示信号未阻塞然后通过 handler 进行处理 sigset_t sigset_t 是 Linux 为用户提供的一个位图但是不允许用户直接修改 每个信号只有一个bit的未决标志非0即1不记录该信号产生了多少次,阻塞标志也是这样表示的因此未决和阻塞标志可以用相同的数据类型sigset_t来存储sigset_t称为信号集这个类型可以表示每个信号的“有效”或“无效”状态在阻塞信号集中“有效”和“无效”的含义是该信号是否被阻塞而在未决信号集中“有效”和“无效”的含义是该信号是否处于未决状态 信号集操作函数 sigprocmask 调用函数sigprocmask可以读取或更改进程的信号屏蔽字阻塞信号集 函数原型int sigprocmask(int how, const sigset_t *set, sigset_t *oldset); how操作类型决定如何修改当前信号屏蔽字可选值 SIG_BLOCK将 set 中的信号 加入 当前屏蔽字取并集SIG_UNBLOCK将 set 中的信号 移除 当前屏蔽字取差集SIG_SETMASK直接用 set 替换 当前屏蔽字 set指向新信号集的指针若为 NULL则不修改屏蔽字oldset保存修改前的旧屏蔽字若为 NULL则不保存 sigset_t是用于表示信号集的数据类型。信号集是一个能够容纳多个信号编号的集合主要用于信号的屏蔽阻塞和等待等操作 sigemptyset() 功能初始化一个信号集将其中所有信号编号清除使其变为空集。语法int sigemptyset(sigset_t *set);其中set是指向要初始化的sigset_t类型信号集的指针。 sigset_t myset; if (sigemptyset(myset) -1) {perror(sigemptyset);return 1; } sigaddset() 功能将一个指定的信号编号添加到已有的信号集中语法int sigaddset(sigset_t *set, int signum);其中set是指向sigset_t类型信号集的指针signum是要添加的信号编号。 sigset_t myset; if (sigemptyset(myset) -1) {perror(sigemptyset);return 1; } if (sigaddset(myset, SIGINT) -1) {perror(sigaddset);return 1; } 使用 sigprocmask 对信号进行阻塞的过程 分别创建一个block_set和一个old_set用于记录要操作和保存哪些信号然后通过sigemptyset确保集合初始化为空接下来将要添加进阻塞队列的信号使用sigaddset添加到block_set中然后就可以使用sigprocmask将block_set中保存的信号添加进内核的阻塞队列中了根据参数 how 的不同做出的操作也就不同 SIG_BLOCK将用户集合中的信号添加到内核屏蔽字位图置 1 // 用户myset {SIGINT} sigprocmask(SIG_BLOCK, block_set, old_set); // 内核block_bitmap | block // 将原本的阻塞队列保存进old_set中 SIG_UNBLOCK将用户集合中的信号从内核屏蔽字移除位图置 0 // 用户myset {SIGINT} sigprocmask(SIG_UNBLOCK, myset, NULL); // 内核block_bitmap ~myset // 解除了当前的阻塞从当前屏蔽字中移除myset中指定的信号NULL表示不保存旧的屏蔽字 // 也可以放入一个sigset_t变量进行保存 SIG_SETMASK直接用用户集合覆盖内核屏蔽字 // 用户myset {SIGINT} sigprocmask(SIG_SETMASK, old_set, block_set); // 内核block_bitmap old_set // 因为最开始的阻塞位图存放在old_set中因此直接将其覆盖回来然后将当前的放入block_set // 这样就是解除了阻塞 完整的流程图 User Space Kernel Space ------------------- --------------------- | | | | | sigset_t myset; | | Process Signal | | sigaddset(...); | | Mask (Block Bitmap)| | | | | ------------------ --------------------| ^| sigprocmask(SIG_BLOCK, myset, ...) |-------------------------------------- 解除屏蔽一般会立即处理当前被解除的信号 pending 位图对应的信号在递达之前就已经被清空了 对信号进行处理时默认该信号会被屏蔽当该信号处理完成时会解除屏蔽 sigpending 读取当前进程的未决信号集,通过set参数传出。调用成功则返回0,出错则返回-1 函数原型int sigpending(sigset_t *set); 通过 sigismember 判断 pending 位图中的信号是否未决函数原型 int sigismember(const sigset_t *set, int signum); 进程对信号的处理方式 处理信号就是递达信号对信号的处理有 3 种方式 默认动作忽略动作自定义处理信号的捕捉 进程处理信号通常都是默认的默认动作包括终止自己、暂停、忽略 自定义处理signal(2,hadler)默认动作signal(2,SIGDFL)忽略动作signal(2,SIGIGN) 信号可能不会立即处理而是在进程从内核态返回到用户态的时候进行处理 对信号的捕捉 如果信号的处理动作是用户自定义函数在信号递达时就调用这个函数这称为捕捉信号。如: 用户程序注册了SIGQUIT信号的处理函数sighandler 当前正在执行main函数这时发生中断或异常切换到内核态。 在中断处理完毕后要返回用户态的main函数之前检查到有信号SIGQUIT递达。 内核决定返回用户态后不是恢复main函数的上下文继续执行而是执行sighandler函数此时需要从内核态转换到用户态来执行sighandler和main函数使用不同的堆栈空间它们之间不存在调用和被调用的关系是两个独立的控制流程。sighandler函数返回后自动执行特殊的系统调用sigreturn再次进入内核态。 如果没有新的信号要递达这次再返回用户态就是恢复main函数的上下文继续执行了 地址空间 以 32 位机器为例在进程的 task_struct 中的 mm_struct 中有 3GB 的用户空间和 1GB 的内核空间操作系统将自身通过内核级页表映射到 mm_struct 中因为操作系统中有很多进程因此所有的进程的内核空间都指向同一个内核级页表无论进程如何切换都能找到同一个 OS因此进程访问 OS 也是在自己的地址空间中的和访问库函数没有区别用户访问内核地址空间中的数据时需要受到约束因此只能通过系统调用进行访问 键盘输入数据的过程 键盘向系统中输入数据的时候会向 CPU 发送硬件中断信号每一个硬件设备都会有自己的中断号CPU 中的寄存器接收到中断号作为一个数组的下标传给内存中的函数指针数组然后通过这个中断向量表中的内容执行对应硬件的操作 中断是纯硬件实现的而信号是硬件软件 操作系统的运行过程 操作系统本质就是一个死循环时钟中断不断调度系统的任务 外部中断的目的就是为了让 CPU 中的寄存器内部生成一个中断号的数字因此可以直接跳过外部生成中断CPU 内部生成一个中断号的数字这个就是 CPU 陷入CPU 寄存器内部生成一个 0x80然后到内存中的中断向量表找到对应的操作 用户进程不能直接进入内核空间中因此需要特定条件下才能跳转过去在 CPU 中有一个 code segment 寄存器这个寄存器中保存着代码段的范围这个寄存器的低两位保存着当前是用户态还是内核态00 表示内核态11 表示用户态当需要执行内核空间中的代码时CPU 先检查当前是用户态还是内核态如果是用户态则转换为内核态寄存器就保存内核空间中相应的代码段开始执行对应的系统调用同理需要执行用户空间的代码时则转换为用户态寄存器就保存内核空间中相应的代码段继续执行用户空间的相应代码 理解系统调用 系统中有一个 sys_call_table当需要调用系统调用时只需要找到对应数组的下标这个下标叫做系统调用号就能执行对应的系统调用了执行系统调用时会先将系统调用的内容写入到中断向量表中接下来CPU 内部生成 0x80 进入中断然后进入中断向量表找到对应的操作这样就成功执行了系统调用 sigaction 原型int sigaction(int signo, const struct sigaction *act, struct sigaction *oact); sigaction函数可以读取和修改与指定信号相关联的处理动作。调用成功则返回0出错则返回-1。signo是指定信号的编号。若act指针非空则根据act修改该信号的处理动作。若oact指针非空则通过oact传出该信号原来的处理动作。act和oact指向sigaction结构体 struct sigaction {void (*sa_handler)(int);void (*sa_sigaction)(int, siginfo_t *, void *);sigset_t sa_mask;int sa_flags;void (*sa_restorer)(void); }; 将sa_handler赋值为常数SIG_IGN传给sigaction表示忽略信号赋值为常数SIG_DFL表示执行系统默认动作赋值为一个函数指针表示用自定义函数捕捉信号或者说向内核注册了一个信号处理函数该函数返回值为void可以带一个int参数通过参数可以得知当前信号的编号这样就可以用同一个函数处理多种信号。显然,这也是一个回调函数不是被main函数调用而是被系统所调用 执行 handler 函数时会自动将正在处理的信号屏蔽处理完成后自动解除屏蔽这样防止了对函数的递归调用导致的系统异常 struct sigaction action,oaction; action.sa_handlerhandler;//设置默认信号处理为handler sigemptyset(action.sa_mask);//将掩码置空 sigaddset(action.sa_mask,3);//对其他信号也进行屏蔽将信号添加进掩码中 action.sa_flags0; sigaction(2,action,oaction); 可重入函数 可重入函数Reentrant Function是指一个函数可以被多个任务如多个线程或进程同时调用或者被一个任务递归调用并且在执行过程中不会出现错误或不一致的情况。也就是说函数在被并发或递归调用时其执行结果和单独调用时是一样的不会因为调用的重叠而破坏自身的数据或其他相关资源的状态 如果一个函数符合以下条件之一则是不可重入的: 调用了malloc或free因为malloc也是用全局链表来管理堆的调用了标准I/O库函数。标准I/O库的很多实现都以不可重入的方式使用全局数据结构 特点 不使用静态或全局数据可重入函数不依赖于静态或全局数据因为这些数据在多个任务间共享容易导致数据竞争 不修改自身代码代码在运行期间不可变 不调用不可重入函数如果一个函数调用了不可重入的函数那么它自身也变成不可重入的 不使用硬件资源在多任务环境中如果函数依赖于特定的硬件资源如特定的寄存器并且这些资源在不同任务间共享可能导致结果不可控所以可重入函数通常不依赖这些资源 不可重入函数 被重入时出现问题的函数称为不可重入函数 不可重入函数在并发调用时可能导致数据损坏或逻辑错误通常因为它们依赖共享状态如静态变量、全局变量或硬件资源 特点 依赖静态/全局数据例如使用静态缓冲区或全局计数器可能修改共享资源如文件操作、内存分配malloc/free存在副作用多次调用可能产生不确定结果 volatile 关键字 它主要用于告诉编译器被修饰的变量可能会在程序的外部被改变例如被硬件设备、其他线程或者操作系统等改变。编译器在编译代码时对于普通变量可能会进行一些优化比如将变量的值缓存在寄存器中以提高访问速度。但是对于volatile修饰的变量编译器不会进行这样的优化每次访问该变量时都会从内存中读取它的值。 #include stdio.h #include stdlib.h #include signal.h #include setjmp.hstatic jmp_buf env; static volatile int flag 0;void handler(int signum) {flag 1;longjmp(env, 1); }int main() {if (signal(SIGINT, handler) SIG_ERR) {perror(signal);return 1;}int ret setjmp(env);if (ret 0) {// 正常执行的代码while (!flag) {// 这里是一些可能会被中断的代码比如循环等待等}} else {// 从信号处理函数跳转回来后执行的代码printf(Interrupted!\n);}return 0; } 这段代码中若不对 flag 使用 volatile 修饰会导致信号量将内存中的 flag 改变而 while 循环依然使用寄存器中 flag 的旧值导致循环无法结束 SIGCHLD 信号 子进程在终止时会给父进程发SIGCHLD信号该信号的默认处理动作是忽略父进程可以自定义 SIGCHLD信号的处理函数这样父进程只需专心处理自己的工作不必关心子进程了子进程 终止时会通知父进程父进程在信号处理函数中调用wait清理子进程即可 如果有部分进程永远不会退出此时使用信号进行等待必须使用非阻塞等待否则等待时会发生阻塞导致后面的流程都无法执行 signal(SIGCHLD,SIG_IGN); //对收到的信号进行忽略 //系统中也对该信号设置了忽略但是这个相当于系统定义的一种Ignore操作 //系统的IGN和用户的IGN含义不同 //用户设置SIGIGN后子进程退出后就不会对父进程发送信号也就不会僵尸但是父进程无法获取到子进程的退出信息
http://www.w-s-a.com/news/843603/

相关文章:

  • 网站备案号怎么查楼书设计素材网站
  • 网站设计机构有哪些中国建设银行网站登录不上
  • 烟台理工学校网站罗湖建设网站
  • 卑鄙的网站开发公司郑州人才网站
  • 成都专业的网站设计公司文化建设的成就
  • 做书籍封皮的网站如何建网站教程视频
  • 唐山建站公司模板ipfs做网站
  • 贵阳做网站品牌网站模板
  • 紫网站建设我的个人博客
  • 优秀网站菜单网页上的视频怎么下载
  • 龙口建网站公司价格国内的平面设计网站
  • 电子商务网站建设与管理读后感上海市基础工程公司
  • 织梦免费企业网站做网站时,404网页如何指向
  • 摄影工作室网站源码百度为什么会k网站
  • 哪个网站有淘宝做图的素材网站分享做描点链接
  • 做哪个网站零售最好网站空间在哪里
  • 荆州网站建设多少钱南阳做网站推广
  • 网站代理打开个人网站设计源码
  • 做php网站的话要学什么语言wordpress搜索不到
  • 金华官方网站建设网络营销策划模板
  • 网站开发到上线在线生成小程序
  • 动易网站设计方案郑州营销网站建设
  • 怎么上网站做简易注销的步骤郑州大学现代远程教育《网页设计与网站建设》课程考核要求
  • 新乡网站建设新乡长沙本地论坛有哪些
  • 潍坊中企动力做的网站怎么样wordpress接入微博
  • 网站开发者所有权归属网站项目建设的必要性
  • 菜鸟网站编程广州网站设计权威乐云践新
  • 网站做接口到app 价格大地资源免费视频观看
  • 怎么给钓鱼网站做防红网站建设相关的
  • 教育培训的网站建设湖南网站建设小公司