300字范文,内容丰富有趣,生活中的好帮手!
300字范文 > C语言 线程的回收与子线程返回值的接收

C语言 线程的回收与子线程返回值的接收

时间:2019-08-25 07:23:24

相关推荐

C语言 线程的回收与子线程返回值的接收

穿的参数为二级指针

需要用全局变量来返回子线程的返回值

// 、、使用内存映射可以拷贝文件/*对原始文件进行内存映射创建一个新文件把新文件的数据拷贝映射到内存中通过内存拷贝将第一个文件的内存映射区拷贝到第二个文件的内存映射区释放资源*/// 匿名映射,不需要文件实体来进行内存映射// 只能用于有血缘关系的进程间通信#include <sys/mman.h>#include <pthread.h>#include <fcntl.h>#include <sys/stat.h>#include <signal.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <stdlib.h>#include <sys/time.h>#include <sys/types.h>#include <sys/wait.h>#include <unistd.h>// int main()// {/*// kill函数// pid》0将信号发送给指定进程// =0:将信号发送给当前进程组// =-1:将信号发送给每一个有权限接受这个信号的进程// 《-1:进程组id的绝对值// sig,要发送的信号// kill(getppid(), 9);// kill(getpid(), 9);// raise函数,给当前进程发送信号// sig,要发送的信号,成功返回0,失败返回非0*/// alarm函数// 设置定时器,倒计时,当时间为0的时候,会给当前进程发送一个 SIGALARM信号// 取消定时器,alarm(0)即可// 返回值是unsigned int,倒计时剩余的时间(上一个alarm剩余的时间)// SIGALRARM信号默认终止当前进程,每个进程只能设置一个定时器// int seconds = alarm(5);// printf("%d\n", seconds);// sleep(2);// seconds = alarm(3);// printf("%d\n", seconds);// while(1){// }// 1秒钟电脑能输多少个数?//无论进程处于什么状态,alarm都会正常计时// 实际时间=内核时间+用户时间+io消耗的时间// alarm(1);// int i =0;// while(1){//printf("%d\n",i++);// }// settimeer函数,用于替换alarm函数,且精度比alarm要高很多,// 参数// which,定时器以什么时间计时//ITIME_REAL: 真实时间,时间到达,就发送SIGALRM//ITIME_VIRTUAL;用户时间,时间到达就发送SIGVTALRM//ITIMER_PROF:进程在内核状态下消耗的时间// 过3秒后,每两秒执行一次// struct itimerval new_value;// // 设置值// new_value.it_interval.tv_sec = 2;// new_value.it_interval.tv_usec =0;// new_value.it_value.tv_sec=3;// new_value.it_value.tv_usec=0;// int ret = setitimer(ITIMER_REAL,&new_value,NULL);// printf("定时器开始\n");// if (ret==-1){//perror("settimer");//exit(0);// }// getchar();// signal捕获信号// sigkill,sigstop既不能被捕捉也不能被忽略// signum:要捕捉的信号// handler:捕捉到信号之后如何处理//sig_ign:忽略//sig_dfl:使用信号默认的行为//回调函数:捕获到信号后执行该函数// 过3秒后,每两秒执行一次// 注册信号捕捉函数//忽略信号// signal(SIGALRM,SIG_IGN);//直行信号的默认动作(sig_ALRM结束程序)// signal(SIGALRM,SIG_DFL);// void (*sig_handler)(int),这是一个函数指针。返回void,参数int,函数名称:sig_handler// 获取当前线程的现成idint asda =10;void *sig_handler(void* arg) {printf("%d\n",*(int*)arg);printf("捕获到子线程:\n");// sleep(3);printf("lllllllllllllll]n的、n%ld\n",pthread_self());// return NULL;pthread_exit((void*)&asda);}//信号集//产生但是还没有被处理的信号被归到未决信号集//sigint信号状态被存储在第二个bit位上// bit位为1,说明信号处于未决状态// 未决状态对的信号需要备处理// 但是在处理之前需要和另一个叫做阻塞信号集的对应比特位进行比较// 如果对应位置是1,那么就说明信号被阻塞,那么这个信号就不会被处理,直到指变成0// 阻塞信号集默认不阻塞任何信号,我们可以手动进行设置(调用系统API)// sigemptyset函数//清空信号集中的数据,所有标志位被设置为0//参数:set,要设置的信号集// sigfillset函数//设为1// sigaddset函数//设置信号集中的某一个标志位设置为1// sigdelset 函数//和上面的相反,0// sigismember函数//判断某个信号是否阻塞// 上面的函数都是阻塞信号集的操作函数// 创建一个信号集// sigset_t set ;// // 先清空// sigemptyset(&set);// // 判断信号是否在信号集中// int ret = sigismember(&set,SIGINT);// if (ret == 0) {// printf("SIGINT 不阻塞\n");// }else if(ret == 1) {// printf("SIGINT 阻塞\n");// }// // 添加信号到信号集中// sigaddset(&set,SIGINT);// sigaddset(&set,SIGQUIT);// ret = sigismember(&set,SIGINT);// if (ret == 0) {// printf("SIGINT 不阻塞\n");// }else if(ret == 1) {// printf("SIGINT 阻塞\n");// }// ret = sigismember(&set,SIGQUIT);// if (ret == 0) {// printf("SIGQUIT 不阻塞\n");// }else if(ret == 1) {// printf("SIGQUIT 阻塞\n");// }// sigdelset(&set, SIGQUIT);// ret = sigismember(&set,SIGQUIT);// if (ret == 0) {// printf("SIGQUIT 不阻塞\n");// }else if(ret == 1) {// printf("SIGQUIT 阻塞\n");// }// 系统调用设置信号集// sigprocmask// 该函数可以将我们自定义的信号集映射到内核中// how://如何对内核中的阻塞信号集进行处理// sig_block,mask|set// SIG_UNBLOCK: mask^set(异或操作// sig_setmask 覆盖内核的指// sigpending//获取内核当中的未决信号集// 编写一个程序,将所有的常规信号(1-31)的未决状态打印出来// 设置某些信号是阻塞的,通过键盘来产生这些信号ctrl+?// 设置2、3信号阻塞// sigset_t set;// sigemptyset(&set);// // 将2、3信号添加到信号集中// sigaddset(&set,SIGINT);// sigaddset(&set,SIGQUIT);// //修改内核中的阻塞信号集// sigprocmask(SIG_BLOCK,&set, NULL);// int num=0;// while(1) {//printf("num:%d\n",num);//if(num == 10){// // 解除sigint的阻塞// sigprocmask(SIG_UNBLOCK,&set,NULL);//}//num++;//// 获取当前的未决信号集//sigset_t pendingset;//sigemptyset(&pendingset);//sigpending(&pendingset);////遍历bit位//for(int i=1;i<=32;i++) {// if(sigismember(&pendingset,i)==1){//printf("1");// }else if(sigismember(&pendingset, i)==0) {//printf("0");// }else{//perror("sigismember\n");exit(0);// }//}printf("\n");sleep(1);// }// sigaction// 检查或者改变信号的处理方式// signum,需要捕捉的信号// act,捕捉到信号后需要执行的动作// oldaact,没用// struct sigaction//sa_handle:回调函数指针//临时阻塞信号集//sa_mask//临时阻塞某些信号// 使用那个信号处理对信号进行处理。如果是0表示使用回调函数//// 必须在设置定时器之前注册回调函数// 最好使用sigaction去注册回调函数// struct sigaction act;// act.sa_flags = 0;// act.sa_sigaction = sig_handler;// //清空临时阻塞信号集// sigemptyset(&act.sa_mask);// sigaction(SIGALRM,&act,NULL);// // sig_t retr = signal(SIGALRM,sig_handler);// // if(retr==SIG_ERR) {// //perror("signal注册");// //exit(-1);// // }// struct itimerval new_value;// // 设置值// new_value.it_interval.tv_sec = 2;// new_value.it_interval.tv_usec =0;// new_value.it_value.tv_sec=3;// new_value.it_value.tv_usec=0;// int ret = setitimer(ITIMER_REAL,&new_value,NULL);// printf("定时器开始\n");// if (ret==-1){//perror("settimer");//exit(0);// }// // getchar();// // while(1);// sigchild信号产生的条件//子进程终止//子进程接收到sigstop信号停止//子进程处于停滞状态,收到sigcont后唤醒// 父进程默认葫芦该信号// 可以用于解决僵尸进城的问题#include<sys/time.h>#include<time.h>void sig_handler2(int num){time_ttm2 = time(NULL);struct tm* loc = localtime(&tm2);// char buf[1024];// sprintf(buf, "%d-%d-%d %d:%d:%d\n",loc->tm_year,loc->tm_mon,loc->tm_mday,loc->tm_hour,loc->tm_min,loc->tm_sec);// printf("%s\n",buf);char* str =asctime(loc);int fd =open("time.txt",O_RDWR|O_CREAT|O_APPEND,0664);write(fd,str,strlen(str));close(fd);// printf("捕捉奥得信号:%d\n",num);// // 回首紫禁城// // while(1){// // wait(NULL);}// while (1)// {int ret =waitpid(-1,NULL,WNOHANG);///* code *///if(ret>0){// printf("二字挂了:%d\n", ret);//}else if(ret ==0) {// // 说明还有子进程或者// break;//}else if(ret ==- 1){// // 没有紫禁城了// break;//}// }}#include<sys/shm.h>int main(){//// 提前设置好阻塞信号集//// 阻塞sigchild//// 因为UN在西main这种可能:////子进程在注册号回调函数之前就已经结束了// sigset_t set;// sigemptyset(&set);// sigaddset(&set,SIGCHLD);// sigprocmask(SIG_BLOCK,&set ,NULL);// pid_t pid;// int count=20;// for (size_t i = 0; i < count; i++)// {//pid = fork();//if(pid==0){// break;//}///* code */// }// // 捕捉子进程死亡时发送的sigchild信号// struct sigaction act;// act.sa_flags=0;// act.sa_sigaction = sig_handler2;// sigemptyset(&act.sa_mask);// sigaction(SIGCHLD,&act,NULL);// // 注册完信号捕捉之后,就接触阻塞// sigprocmask(SIG_UNBLOCK,&set,NULL);// if(pid>0){//// 父进程//while(1){// printf("我是你爹\n");// sleep(2);//}} else if(pid==0){// printf("儿字:%d\n",getpid());//}// pid_t pid = fork();// if(pid==0){//for(int i=0;i<5;i++) {// printf("孩子进程%d\n", i);// sleep(1);//}// }else if(pid>0) {// printf("爹进程\n");// sleep(2);// printf("傻儿子\n");// kill(pid,SIGINT);// }// 共享内存// 创建一个新的内存共享段// 或者获取一个 既有的共享内存段// shmat和当前进程进行关联// shmdat,移除和当前进程的关联// shmctl// 创建一个共享内存// int shmid = shmget(100,4096,IPC_CREAT|0664);// // 和当前进程进行关联// void* ptr = shmat(shmid,NULL,0);// printf("%d\n", shmid);// char*str = "hello world";// memcpy(ptr,str,strlen(str)+1);// printf("按任意键继续\n");// getchar();// shmdt(ptr);// shmctl(shmid,IPC_RMID,NULL);// ftok函数,根据指定的路径名和int指生成一个共享内存的key// 虽然是int类型的指,但是内核只会使用他的一个字节,也就是说范围其实是0-255// 操作系统如何知道一块共享内存有多少个进程关联//共享内存维护了一个结构体,struct shmid——ds//该结构体中有一个成员shm_noattach记录了相关信息//ipcs -m可以查看// 编写一个守护进程,每隔两秒获取一下系统时间,将这个时间写入磁盘文件中// 创建子进程,推出父进程// pid_t pid =fork();// if(pid>0){//exit(0);// }// // 将子进程提升为回话,// setsid();// // 设置掩码// umask(022);// // 更改工作目录// chdir("/");// // 关闭并重定向文件描述符// // int fd = open("/dev/null",O_RDWR);// // dup2(fd,STDIN_FILENO);// // dup2(fd,STDOUT_FILENO);// // dup2(fd,STDERR_FILENO);// // 业务逻辑// // 创建定时器// // setitimer(ITIMER_REAL,&val,NULL);// // 捕捉定是信号// struct sigaction act;// act.sa_flags = 0;// act.sa_sigaction = sig_handler2;// sigemptyset(&act.sa_mask);// sigaction(SIGALRM,&act,NULL);// // struct itimerval new_value;// // 设置值// struct itimerval new_value;// new_value.it_interval.tv_sec = 2;// new_value.it_interval.tv_usec =0;// new_value.it_value.tv_sec=2;// new_value.it_value.tv_usec=0;// int ret = setitimer(ITIMER_REAL,&new_value,NULL);// while(1){//sleep(10);// }// pthread_create函数//用于创建一个子线程// 一般情况下,main函数所在的县城的为主县城// 其余创建的现成为子线程// 程序中默认只有一个线程(主线程)// 调用pthread_create创建一个新的县城pthread_t tid ;// 创建一个子线程int num = 10;int ret = pthread_create(&tid,NULL,sig_handler,(void*)&num);if(0!=ret){char* errstr = strerror(ret);printf("error: %s\n", errstr);}for (int i = 0; i < 10; i++){printf("%d\n",i);/* code */}printf("子线程id%ld主线程ID:%ld\n", tid,pthread_self());// 回首紫禁城int* asdasdasd ;int caousod = pthread_join(tid,(void **)&asdasdasd);if(ret!=0){char* errstr = strerror(ret);printf("error: %s",errstr);} printf("紫禁城的返回值%d\n",*asdasdasd);printf("子线程资源回收成功\n");// sleep(10);// 终止一个子线程// pthread-exit//需要传递一个指针作为返回值//可以再pthread_join中获取到// 终止一个县城,在哪个现成中调用,就终止哪个现成// 让主线程退出// 不会影响其他县城pthread_exit(NULL);// printf("我他妈不会执行\n");// // 比较两个现成id是否相等// // pthread_equal// // 不同的操作系统,,实现发哪个是可能不太一样有的是无符号长正兴(大部分),有的是结构体类型// pthead_join// 挥手自现成的资源。和wait差不多// 这个函数是阻塞的// 调用一次智能回收一个子线程// ,一般在主线程中使用// retvalu: 勇于接受子线程退出时的返回值// 二级指针return 0;}/*// char * buf;// strcpy(buf, "cao nima");return 0;}/*// 修改mmap的flags参数,之前使用的是MAP_SHARED// 现在我们要用的是MAP_ANONint len = 1204;void *ptr = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_ANON | MAP_SHARED, -1, 0);if (ptr == MAP_FAILED){perror("mmap");exit(0);}// 父子进程间通信int pid = fork();if (pid > 0){strcpy((char *)ptr, "hello world");wait(NULL);}else if (0 == pid){sleep(1);printf("%s\n", (char *)ptr);}// 释放内存映射区int ret = munmap(ptr, len);// int fd = open("englsih.txt", O_RDONLY);// // 获取原始文件的大小// int len = lseek(fd, 0, SEEK_END);// // 创建一个新文件,并对其大小进行拓展// int fd1 = open("cpy.txt", O_CREAT | O_RDWR, 0664);// truncate("cpy.txt", len);// write(fd1, " ", 1);// // 分别进行内存映射// void *ptr = mmap(NULL, len, PROT_READ, MAP_SHARED, fd, 0);// void *ptr1 = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd1, 0);// if (ptr == MAP_FAILED)// {//perror("mmap");//exit(0);// }// if (ptr1 == MAP_FAILED)// {//perror("mmap");//exit(0);// }// // 内存拷贝// memcpy(ptr1, ptr, len);// munmap(ptr1, len);// munmap(ptr, len);// close(fd1);// close(fd);return 0;}*/

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。