1:程序如何开始
- 编译链接时的引导代码:操作系统性在执行main函数前其实也要先执行一段引导代码才能执行main,链接时由连接器将编译器中事先准备好的引导代码给链接进去和我们的应用程序一起构成最终的可执行程序。
- 运行时的加载器:加载器是操作系统中的程序,当我们执行一个程序时(譬如./a.out,譬如代码中用exec族函数来运行时)加载器负责将这个程序加载到内存中去执行这个程序。
- 程序在编译时用到链接器,运行时用加载器,这两个东西对程序运行原理非常重要。
- argc和argv的传参如何实现
先传送到加载器再到引导代码在传给main()函数
2:程序如何结束
- 正常终止:return、exit、_exit
- 非正常终止:自己或他人发信号终止进程
3:主线程main()函数执行
- 主线程main()函数开始执行,那么我们自己创建的线程,也需要从一个函数开始运行(初始函数),一旦这个函数运行完毕,就代表我们这个线程运行结束。
- 整个进程是否执行完毕的标志是:主线程是否执行完,如果主线程执行完毕了,就代表这个进程执行完毕了,此时如果其他字线程还没执行完,也会被强行终止。
- 所以,一般情况下,如果想保持子线程(比如自己创建的线程)的运行状态,就要让主线程一种保持运行,不要让主线程运行完毕。
// mian.cpp
#include<iostream>
#include <thread>
void myJob()
{
std::cout << " 我的线程开始了" << std::endl;
std::cout << " 我的线程执行完毕" << std::endl;
}
int main()
{
//thread是一个类,创建一个类对象myobj
// 打印 myJob 线程
std::thread myThread(myJob);
std::cout << "myJob线程:" << myThread.get_id() << std::endl;
myThread.join();
// 打印主线程
std::cout << "主线程:" << std::this_thread::get_id() << std::endl;
std::cout << " I love China" << std::endl;
return 0;
}
std::thread myThread(myJob);
这条语句包括以下要点:
- thread是一个类,创建一个类对象myThread,而myJob为可调用对象(作为实参去构造myThread对象)
- 创建了线程,线程执行起点(入口)是myJob;
- myJob线程开始执行(即运行到这条语句时,子线程就开始执行了)
对于myThread.join();,这条语句包括以下要点:
- join():汇合,即阻塞,阻塞(当前线程)主线程,让(当前线程)主线程等待子线程执行完毕,然后子线程和子线程汇合,然后主线程再往下走。
- 即主线程阻塞到这里等待myJob()执行完,当子线程执行完毕,这个jion就执行完毕,主线程就继续往下走。
- 一句话:阻塞主线程并等待子线程执行完
参考文献