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

常州外贸网站建设合肥网站建设公司 推荐

常州外贸网站建设,合肥网站建设公司 推荐,门窗设计软件免费版,wordpress 图片宽度目录 概念信号产生信号注册信号注销信号处理实例 信号的基本应用 概念 进程信号: 概念:信号就是软件中断。信号就是用于向进程通知某个事件的产生,打断进程当前操作,去处理这个事件。 linux中信号的种类:使用kill -l命…

目录

  • 概念
  • 信号产生
  • 信号注册
  • 信号注销
  • 信号处理
    • 实例
  • 信号的基本应用

概念

进程信号:
概念:信号就是软件中断。信号就是用于向进程通知某个事件的产生,打断进程当前操作,去处理这个事件。
linux中信号的种类:使用kill -l命令查看所有信号–62种
1~31:非可靠信号(有可能会造成事件丢失)
34~64:可靠信号(不会丢失事件)
信号的生命周期:产生信号->在进程pcb中注册信号->注销信号->处理信号

信号产生

信号的产生
硬件产生
ctrl+c 退出进程
ctrl+| 退出进程
ctrl+z 暂停进程,此时ps -aux | grep 进程名称 可以看到进程处于停止状态。jobs:查看作业,通过fg 作业id:让停止作业继续运行
软件产生
kill命令发送信号给指定进程 kill -signum pid
kill命令杀死一个进程的原理:默认给进程发送了终止信号
int kill(pid_t pid, int sig); 给pid进程发送sig信号
int raise(int sig); – 给进程自身发送一个指定的信号
unsigned int alarm(unsigned int seconds);
–sec秒之后给进程自身发送一个时钟信号–SIGALRM
void abort(void); – 给进程自身发送一个SIGABRT信号
int sigqueue(pid_t pid, int sig, const union sigval value);
给一个进程发送信号的同时携带一个数据过去

信号注册

信号的注册
注册:在进程中注册一个信号让进程直到自己收到了某个信号
修改pending位图(用于标记是否收到了某个信号),添加一个信号信息节点
非可靠:如果信号没有被注册,则注册;否则什么都不做。链表中不会出现相同非可靠信号信息节点
可靠:不管信号是否注册,都会注册一下。链表中有可能又多个相同的信号信息节点。
sigqueue-双向链表 – 表示有多少信号

信号注销

信号的注销
注销:将信号信息进程pcb中一处(修改位图,删除节点)
非可靠:删除节点,修改位图为0
可靠:删除一个信号节点,检查链表中是否还有相同节点,没有则修改位图

信号处理

信号的处理
处理:信号的处理也叫信号的递达,实际上就是打断进程当前的操作,去执行进程的对应信号处理函数。
信号的处理方式:
1.默认处理方式
2.忽略处理方式
3.自定义处理方式–用户自己定义信号的处理回调函数
typedef void(*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
signum:信号值-表示要修改哪个信号的处理方式
handler:新的信号处理方式
SIG_DEL-默认;SIG_IGN-忽略;自定义函数的名称
返回值:成功则返回当前信号原来的处理方式

自定义处理方式的信号捕捉流程
信号是从程序运行从内核态返回用户态之前处理的。
程序处理信号时在内核态,当遇到回调函数自定义时,因为自定义函数是用户自己写的,返回用户态执行,完成后如果还有信号则继续返回内核态进行,当信号处理完成后返回用户态主流程。
程序运行可以通过中断,异常,系统调用从用户态运行切换到内核态

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<signal.h>void sigcb(int signo)
{printf("recv signal:%d\n", signo);printf("时间到了\n");alarm(3);
}
int main(int argc, char *argv[])
{signal(信号,处理方式)signal(SIGALRM, sigcb);kill(进程ID,信号值)//kill(getpid(), SIGINT);//raise(SIGINT);alarm(3);while(1){printf("-----\n");sleep(1);}return 0;
}

阻塞:信号的阻塞–阻止信号被递达
一个信号被阻塞后,依然收到这个信号会注册,但是暂时不被处理
pcb中有pending位图-未决信号结合;还有阻塞信号集合
如果要阻塞一个信号,就是在进程的阻塞信号集合中标记这个信号
具体操作:
int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
how:操作类型
SIG_BLOCK-- 阻塞set集合的信号 block = block | set
SIG_UNBLOCK – 将set集合中的信号解除阻塞 block &= ~set
SIG_SETMASK–将set集合中的信号设置为阻塞集合的信号block=set
返回值:成功返回0;失败返回-1

实例

先自定义特定信号的处理方式–做打印收到了哪个信号 signal
将所有信号阻塞 sigprocmask block
让程序运行停下来,在这期间给进程发送信号getchar
解除这些信号的阻塞,查看信号处理结果 sigprocmask unblock

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<signal.h>void sigcb(int signo)
{printf("recv signal:%d\n", signo);
}
int main(int argc, char *argv[])
{signal(SIGINT, sigcb);signal(40, sigcb);sigset_t set;sigemptyset(&set);sigfillset(&set);//zu sesigprocmask(SIG_BLOCK, &set, NULL);printf("回车后,继续运行\n");getchar();printf("解除信号阻塞,查看结果\n");sigprocmask(SIG_UNBLOCK, &set, NULL);while(1){sleep(1);}return 0;
}

通过实例,按三次ctrl c,输入四次kill -40命令。最终结果显示ctrl c一次,kill -40四次。
因为ctrl c是SIGINT,在前31属于不可靠信号,因此同时发送阻塞只保留一个。kill -40属于可靠信号,每次发送都保留,等阻塞结束后依次回调。

两个比较特殊的信号:SIGKILL/SIGSTOP 这两个信号不可被阻塞,不可被自定义,不可被忽略,说白了就是无法修改处理方式。

信号的基本应用

信号的基本应用:
SIGCHLD信号:一个子进程退出后,给父进程发送的子进程状态改变信号
但是SIGCHLD默认处理方式就是什么都不做
要避免僵尸进程,则需要在父进程中wait阻塞等待。
如果不想阻塞等待,则可以使用信号来解决
自定义SIGCHLD信号的处理方式,在回调函数中调用waitpid接口
SIGCHLD是一个非可靠信号–意味着多个子进程同时退出,有可能丢失事件
signal(SIGCHLD,SIG_IGN);–显式忽略

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<signal.h>
#include<sys/wait.h>void sigcb(int no)
{printf("son fork exit\n");waitpid(-1, NULL, 0);
}
int main(int argc, char *argv[])
{signal(SIGCHLD, sigcb);pid_t pid = fork();if(pid == 0){ sleep(3);exit(0);}while(1){printf("------\n");sleep(1);}return 0;
}

waitpid();有子进程退出返回值>0;没有子进程退出返回值==0;出错<0
wait(-1, NULL, WNOHANG)
-1:等待任意一个子进程的退出
NULL:返回值不关心
WNOHANG:将接口设置为非阻塞

SIGPIPE:管道所有读端被关闭则write出发异常对应的信号
SIGPIPE信号默认处理方式就是退出进程,若不想退出则需要自定义/忽略

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<errno.h>
#include<fcntl.h>
#include<sys/stat.h>
#include<string.h>
#include<signal.h>void sigcb(int no)
{printf("all pipe read is close\n");
}
int main(int argc, char *argv[])
{
//更换信号处理方式signal(SIGPIPE, sigcb);umask(0);char *fifo_name = "./test.fifo";int ret = mkfifo(fifo_name, 0664);if(ret < 0 && errno != EEXIST){perror("mkfifo error");return -1;}int fd = open(fifo_name, O_WRONLY);if(fd < 0){perror("open error");return -1;}while(1){char buf[1024] = {0};scanf("%s", buf);int ret = write(fd, buf, strlen(buf));if(ret < 0){perror("write error");return -1;}}close(fd);return 0;
}

关键字:volatile
功能:保持内存可见性–让cpu每次访问变量的时候都从内存中重新获取数据
目的:防止编译器过度优化

可重入函数与不可重入函数:
函数的重入:在不同的执行流程中(main、signal)同时进入一个函数进行执行。
不可重入:一个函数重入后,有可能会造成数据二义或者逻辑混乱。
可重入:一个函数重入后,不会出现问题。
函数是否可重入的重点:一个函数中是否对全局数据进行不受保护的非原子操作(是-不可重入)

//不可重入
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<signal.h>int a = 0, b = 0;int test()
{a++;sleeo(1);b++;printf("%d + %d = %d\n",a, b, a+b);
}void sigcb(int no)
{test();
}int main(int argc, char *argv[])
{signal(SIGINT, sigcb);test();return 0;
}
http://www.yayakq.cn/news/11257/

相关文章:

  • 网站设计确认书抖音营销ppt课件
  • 网站首页域名如何设置访问快wordpress 外勤人员
  • jq动画效果网站做网站抽奖系统
  • 上海 高端 网站建设东营信息网招聘信息
  • 公司网页网站如何做wordpress支持MySQL5.5
  • 网站建设一条龙源码安卓市场2022最新版下载
  • 重庆建站模板搭建广州建设工程造价管理站网站
  • 华西医院网站开发青岛高端网站设计
  • 重庆茂尔建设集团有限公司网站成都网站建设推广详
  • 中煤建设集团网站怎样做网站教程
  • 永德网站建设360信息流广告在哪里展示
  • 怎么做一张图片的网站广府网站建设
  • 做网站选哪个语言合肥网站建设网站推广
  • 黑别人网站泉州网站建设价钱
  • 网站建设的公司哪家是上市公司客源网站
  • 高端商品网站展架立式落地式
  • 中牟网站制作公司网站维护流程
  • 网站备案提交信息吗有哪些做国际贸易的网站
  • 郑州电商网站建设2021年年度关键词排名
  • 公司建设网站需要什么条件素材网址
  • 欧洲购物网站排名海口网站排名提升
  • 闪灵企业建站系统千万别学服装设计
  • 花钱做网站不给源码2022年国际十大新闻
  • 运城网站建设运城天气网站建设平台分析
  • 服装店网站模板免费网站建设合同范本
  • 推广网站发布文章网站建设硬件配置
  • 小型企业类网站开发公司昌吉市住房和城乡建设局网站
  • 网站开发经验教训asp网站可运行jsp吗
  • 山西建设工程备案网站建立企业官方网站
  • 专业ppt制作价格天津seo公司排名