12.线程(一)
一.SIGCHLD信号补充

应该子进程退出的时候,系统默认对其的信号是Ign的,所以我们看不到对应的反应
#include <iostream>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h> // 注意:原代码中使用了sleep函数,需包含此头文件
#include <wait.h>void handler(int signo)
{std::cout << "get a sig: " << signo << std::endl;
}int main()
{signal(SIGCHLD,handler);if(fork() == 0){sleep(5);std::cout << "子进程退出" << std::endl;exit(0);}while(true){sleep(1);}return 0;
}
所以,现在我们对应的子进程退出时,确实会给父进程发送信号,我们就能基于信号,来进行回收子进程
#include <iostream>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h> // 注意:原代码中使用了sleep函数,需包含此头文件
#include <wait.h>void handler(int signo)
{std::cout << "get a sig: " << signo << std::endl;pid_t rid = ::waitpid(-1,nullptr,0);if(rid > 0){std::cout << "子进程退出了,回收成功,child id: " << rid << std::endl;}
}int main()
{signal(SIGCHLD,handler);if(fork() == 0){sleep(5);std::cout << "子进程退出" << std::endl;exit(0);}while(true){sleep(1);}return 0;
}
问题一:
如果是多个子进程一起退出呢?
#include <iostream>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h> // 注意:原代码中使用了sleep函数,需包含此头文件
#include <wait.h>void handler(int signo)
{std::cout << "get a sig: " << signo << std::endl;pid_t rid = ::waitpid(-1,nullptr,0);if(rid > 0){std::cout << "子进程退出了,回收成功,child id: " << rid << std::endl;}
}int main()
{signal(SIGCHLD,handler);for(int i = 0;i < 10; i++){if(fork() == 0){sleep(5);std::cout << "子进程退出" << std::endl;exit(0);}}while(true){sleep(1);}return 0;
}
我们可以尝试循环wait,直到全部都回收
#include <iostream>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h> // 注意:原代码中使用了sleep函数,需包含此头文件
#include <wait.h>void handler(int signo)
{std::cout << "get a sig: " << signo << std::endl;while(true){pid_t rid = ::waitpid(-1,nullptr,0);if(rid > 0){std::cout << "子进程退出了,回收成功,child id: " << rid << std::endl;}else if(rid < 0){std::cout << "暂时:回收完毕" << std::endl;break;} }
}int main()
{signal(SIGCHLD,handler);for(int i = 0;i < 10; i++){if(fork() == 0){sleep(5);std::cout << "子进程退出" << std::endl;exit(0);}}while(true){sleep(1);}return 0;
}
问题二:
如果10个子进程,6个退出了,上面的代码会怎么办?
我们在等待第7个子进程的时候,会出现阻塞现象,我们要进行非阻塞等待
#include <iostream>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h> // 注意:原代码中使用了sleep函数,需包含此头文件
#include <wait.h>void handler(int signo)
{std::cout << "get a sig: " << signo << std::endl;while(true){pid_t rid = ::waitpid(-1,nullptr,WNOHANG);if(rid > 0){std::cout << "子进程退出了,回收成功,child id: " << rid << std::endl;}else if(rid == 0){std::cout << "退出的子进程已经全部回收了" << std::endl;break;}else{std::cout << "wait error" << std::endl;break;} }
}int main()
{signal(SIGCHLD,handler);for(int i = 0;i < 10; i++){if(fork() == 0){sleep(5);std::cout << "子进程退出" << std::endl;exit(0);}}while(true){sleep(1);}return 0;
}

还有一个简单操作,能直接对子进程进行回收
#include <iostream>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h> // 注意:原代码中使用了sleep函数,需包含此头文件
#include <wait.h>int main()
{//linux下 如果只想不产生僵尸,我们直接进行SIG_IGN就行了signal(SIGCHLD,SIG_IGN);for(int i = 0;i < 10; i++){if(fork() == 0){sleep(5);std::cout << "子进程退出" << std::endl;exit(0);}}while(true){sleep(1);}return 0;
}
但是我们的SIG_IGN只是在linux下有用,我们手动设置的IGN和默认的IGN是不一样的
二.线程概念

![]()
三.Linux下线程的概念



![]()


一个执行流就是一个线程
四.进程 vs 线程



![]()
五.接口验证

#include <iostream>
#include <unistd.h>
#include <pthread.h>//新线程
void* run(void* args)
{while(true){std::cout << "new thread" << std::endl;sleep(1);}return nullptr;
}int main()
{pthread_t tid;pthread_create(&tid,nullptr,run,(void*)"thread-1");//主线程while(true){std::cout << "main thread" << std::endl;sleep(1);}return 0;
}

如果是较新的版本,可能会自动带上我们对应的选项
"makefile"mythread:mythread.ccg++ -o $@ $^ -std=c++11 -lpthread
.PHONY:clean
clean:rm -rf mythread
这里确实是两个执行流
#include <iostream>
#include <unistd.h>
#include <pthread.h>//新线程
void* run(void* args)
{while(true){std::cout << "new thread, pid: " << getpid() << std::endl;sleep(1);}return nullptr;
}int main()
{std::cout << "我是一个进程: " << getpid() << std::endl;pthread_t tid;pthread_create(&tid,nullptr,run,(void*)"thread-1");//主线程while(true){std::cout << "main thread, pid: " << getpid() << std::endl;sleep(1);}return 0;
}

查看轻量级进程(ps -aL | grep mythread)

PID和LWP相同的就是我们对应的主线程,不相等的就是新线程
![]()
六.地址空间

1.分页式存储管理











![]()
2.多级页表






