线程和进程
最近经常看到多线程和多进程,这两个概念在某些方向还是很像的,但是进程和线程到底有啥联系,又有啥区别,很多人并没有完全弄明白,最近学操作系统的时候,老师经常叫线程为进程的进程,看了网上的一些资料,也有把线程叫做轻量级进程的,今天我从Linux系统中的线程和进程来深入解释一下。
进程和线程的相同点要远远大于不同点。主要依据就是在 Linux 中,无论进程还是线程,都是抽象成了 task 任务,在源码里都是用 task_struct 结构来实现的,这点学过单片机freertos系统的也知道,在运行freertos的操作系统中stm32创建的多线程被称为任务。
struct task_struct {
volatile long state;
pid_t pid;
pid_t tgid;
struct task_struct __rcu *parent;
struct list_head children;
struct list_head sibling;
struct task_struct *group_leader;
int prio, static_prio, normal_prio;
unsigned int rt_priority;
struct mm_struct *mm, *active_mm;
struct fs_struct *fs;
struct files_struct *files;
struct nsproxy *nsproxy;
...
}
这是一个任务控制块,在linux中进程和线程的所有字段即属性都是一样的,包括状态、pid、task 树关系、地址空间、文件系统信息、打开的文件信息等等字段,线程也都有,他们本质是一个东西,别忘了线程也叫做轻量级进程。
他们的关系与字段下面这两个字段密不可分
struct task_struct {
......
pid_t pid;
pid_t tgid;
}
pid学过操作系统的都知道这个是进程的id号
对于线程来说,如果我们一个进程创建了多个线程,那么每个线程的pid都是不同的,但是我们要知道这个线程是属于哪个进程,即由哪个进程所创建的,tgid就是为了表明该线程是哪个进程创建的,tgid的值是创建当前线程的进程的pid值。
创建进程
#include <iostream>
#include <unistd.h>
using namespace std;
int main() {
pid_t pid = 5;
pid = fork();
if(pid < 0)
cout << "Error in fork!" << endl;
else if (pid == 0) cout << "I am Child1!Pid is " << pid << " B" << endl;
else {
cout << "I am Parent!Pid is " << pid << " A" << endl;
pid_t pid2 = fork();
if (pid2 == 0) cout << "I am Child2!Pid is " << pid2 << " C" << endl;
}
cout << "end." << endl;
return 0;
}
创建进程调用的是fork()函数
创建线程
#include<stdio.h>
#include<pthread.h>
#include<unistd.h>
void* thread_run(void* args)
{
const char* id = (const char*)args;
while(1){
printf("I am %s thread, %d\n", id, getpid());
sleep(1);
}
}
int main()
{
pthread_t tid; //定义一个线程ID
pthread_create(&tid, NULL, thread_run, (void*)"thread 1");
while(1){
printf("I am mian thread, %d\n",getpid());
sleep(1);
}
return 0;
}
创建线程调用的是pthread_create()函数,
他们两个创建时调用的函数虽然不同,但是在底层的创建进程和线程调用的却是同一个函数,
进程创建
SYSCALL_DEFINE0(fork)
{
return do_fork(SIGCHLD, 0, 0, NULL, NULL);
}
long do_fork(...)
{
struct task_struct *p;
p = copy_process(clone_flags, ...);
...
}
线程创建
create_thread (struct pthread *pd, ...)
{
int clone_flags = (CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGNAL
| CLONE_SETTLS | CLONE_PARENT_SETTID
| CLONE_CHILD_CLEARTID | CLONE_SYSVSEM
| 0);
int res = do_clone (pd, attr, clone_flags, ...);
...
}
SYSCALL_DEFINE5(clone, ......)
{
return do_fork(clone_flags, newsp, 0, parent_tidptr, child_tidptr);
}
可见无论是创建进程还是创建线程,都是调用内核中的do_fork()函数
多线程和多进程最大的区别就是他们所在的内存空间不同,多进程程序来说,每一个进程都有独立的地址空间,多进程只是,将父进程的空间复制了一份给子进程,而多线程程序中的所有线程都会共享其父进程的地址空间,子进程,子线程的变量参数改变时,父进程的变量参数并不受影响,因为子进程中的字段数据只是复制了父进程的创建子进程时的数据,而子线程不一样它和创建它的进程时共用一篇内存空间的,子线程中改变的值,同样会影响父进程。文章来源:https://www.toymoban.com/news/detail-467101.html
得出结论进程和线程之间的根本区别在于其内存空间是否与创建它们的父进程是否共享文章来源地址https://www.toymoban.com/news/detail-467101.html
到了这里,关于多线程和多进程的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!