Linux多进程、线程创建管理及状态切换

高级操作系统——XV6进程管理 源代码阅读: type.h:用于声明一些数据类型的简化名称,和声明页表指针的数据类型。 param.h:主要用于声明基本的一些常量,包括内核栈大小等。 memlayout.h:主要用于声明一些和内存与地址相关的常量与方法,包括虚拟内存转物理内存的方法以及物理内存转虚拟内存的方法等。 defs.h:声明在之后文件中要用到的函数。 x86.h:让c代码使用特殊的x86汇编的一些函数包括outb等,并声... 阅读详情

在嵌入式Linux中创建四个进程,2个实时进程,2个非实时进程。每个进程中创建两个线程,在线程中调用系统服务来测试任务可中断睡眠、不可中断睡眠、暂停3种状态的切换,用一个进程来测试进程退出过程。

文章末尾附全部代码~

运行全过程:

创建过程

1、进程创建(主函数中)

(1)当pid==0时,说明此时代码运行是在子进程中,会退出该子进程,以免子进程继续创建子进程,父进程中的pid则为创建的子进程的pid号。

(2)父进程和子进程资源是共享的,包括:

代码段(共享相同的可执行代码)、全局变量和静态变量、打开的文件描述符(文件、管道、信号量等资源)、当前工作目录和进程根目录等

(3)不共享的资源:
进程ID、父进程的堆和子进程的堆(内容相同,但位于的内存空间不同)、栈、信号量和消息队列、打开文件的偏移量

2、子进程创建函数

(1)pid==0,表示只在fork()创建的子进程中执行,父进程会直接跳过该块

3、运行结果

如设想一样,一个父进程创建了三个子进程

4、若注释掉break,让子进程创建子进程

(1)父进程创建了3个子进程

(2)子进程0创建了两个子线程1和2:13150和13149

(3)子进程1创建了一个子线程2:13152

(3)子进程2没有再创建子线程,因为已达for循环末尾

子进程继承父进程的代码从父进程的当刻运行处开始。

5、子线程创建(主函数中):

(1)子进程和父进程的代码段是一样的,需要通过进程的pid号来判断此时是哪个进程在运行。

(2)只有运行到指定进程,才运行该进程相对应的代码。

(3)每个线程的线程体都是单独的,需要分开创建,不能只用单个函数。

6、子线程创建函数

每个线程都有专属于自己的线程体,parent_thread为该线程的线程执行函数

7、子线程体

创建线程后,线程立即开始执行线程体(线程函数)

8、调度策略

(1)普通调度策略:SCHED_OTHER,对应值为0

(2)实时调度策略,先进先出方式调度:SCHED_FIFO,对应值为1

(3)实时调度策略,时间片轮转方式调度:SCHED_RR,对应值为2

9、任务状态切换:S可中断睡眠、D不可中断睡眠、T暂停、Z退出(主函数中)

(1)S可中断睡眠:父进程中不断申请一个信号量,不断等待使进程切换为S可中断睡眠

(2)D不可中断睡眠:将子进程0通过vfork()使创建的子进程先运行(不可中断),进而使进程sleep(100)(进入睡眠)切换为D不可中断睡眠状态

(3)T暂停状态:通过execvp函数给子进程1发送SIGSTOP信号(命令:kill -STOP 进程的pid号)

(4)Z退出状态:通过exit(1)使子进程退出,状态切换为Z退出状态

(5)终端状态查询ps-aux:

相关函数

1、进程创建相关函数:

创建子进程fork():

(1)如果子进程创建成功,在父进程中返回子进程的PID,而在子进程中返回0。

(2)如果子进程创建失败,则在父进程中返回 -1。

getpid():

获取当前进程的PID号

getppid():

获取当前进程父进程的PID号

2、进程调度策略相关函数:

(1)sched_get_priority_max()函数:参数为传入调度策略对应的宏定义。函数为可以获取实时进程优先级的最大值。

(2)sched_setscheduler()函数:第一个参数为需要改变调度策略的目标线程,第二个参数为改变的调度策略,第三个参数为一个结构指针类型,用以指定调度优先级。

(3)sched_getscheduler()函数:参数为需要返回调度策略的进程pid。

3、线程创建相关函数

(1)pthread_create():

创建线程。第一个参数指向线程标识符的指针,第二个参数设置线程的属性,第三个参数是线程运行函数的起始地址,第四个参数为运行函数的参数。

(2)pthread_join():

等待一个指定线程终止,并获取该线程的退出状态。

第一个参数为要等待的线程tid,第二个参数可设为NULL,若不关心退出状态。

(3)gettid():

获取当前线程的tid号(若为进程的主线程,tid号与pid号一致)

(4)pthread_exit():

退出线程,不关心退出值则参数设置为(NULL)

4、任务状态切换相关函数:

(1)可中断睡眠S

sem_open():

创建信号量。第一个参数为信号量的外部名字,第二个参数指定创建或打开信号量的方式和标志位,第三个参数为权限位,第四个参数为信号灯的初值。

sem_wait():

       等待(阻塞)信号量,对信号量进行P操作(等待、减小)

(2)不可中断睡眠D

vfork():

       (1)创建一个新的进程。

       (2)保证子进程先运行,在它调用 exec(进程替换) 或 exit(退出进程) 之后父进程才可能被调度运行。(让程序不可中断)

       (3)子进程中返回0,父进程中返回子进程的PID。

sleep():让当前进程挂起一段时间(进入睡眠)

vfork()与fork()的区别

(1)vfork()相比fork()创建子进程时不会复制父进程的地址空间(包括代码段、数据段、堆和栈),子进程与父进程共享地址空间。

(2)在调用exec函数族之前,它与父进程共享地址空间,因此对共享的数据进行修改会影响到父进程中相同地址空间中的数据。

(3)vfork()相比fork()通常用于立即执行一个新的程序。

(3)暂停状态T:

sprintf():

第一个参数为目的字符串,第二个参数为格式化字符串。该应用中将整数打印到字符串中

execvp():

第一个参数为要运行的命令名称,第二个参数( argv )表示command 的参数列表,是一个char*字符串数组。

(4)退出状态Z:

exit():参数0表示正常退出,非0表示异常退出。

5、程序运行:

sudo gcc -pthread Task2.c -o Task2

(1)sudo:超级用户权限

(2)gcc: GNU编译器集合(GNU Compiler Collection)的命令,用于编译C语言程序

(3)-pthread:告诉编译器链接 POSIX 线程库(pthread),以支持多线程程序。

(4)Task2.c:要编译的源代码文件的名称。

(5)-o Task2:指定编译输出的可执行文件,-o后面的参数是输出文件的名称。

sudo ./Task2

因为需要访问系统级资源,需要超级用户权限。

代码

/*******************************************1、引入函数库***********************************************/
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sched.h>
#include <string.h>
#include <errno.h>
#include<assert.h>
#include<pthread.h>
#include<unistd.h>
//pthread用户库内没有gettid(),所以需要下面的头文件以及gettid()函数定义
#include<sys/syscall.h>
//信号量函数库
#include <semaphore.h>
#include <fcntl.h>
#include <errno.h>
/*******************************************2、函数声明***********************************************/
//进程创建函数
void creat_child_process();             // 创建子进程
void child1_Process_status_change();    // 子进程1状态更改为实时进程
void child2_Process_status_change();    // 子进程2状态更改为实时进程
//线程创建函数
pid_t gettid();                         // 线程号获取函数
void *parent_thread();                  // 父进程的线程体
void *child_pid0_thread();              // 子进程0的线程体
void *child_pid1_thread();              // 子进程1的线程体
void *child_pid2_thread();              // 子进程2的线程体
void create_parent_thread();            // 创建父进程的线程
void create_child_pid0_thread();        // 创建子进程0的线程
void create_child_pid1_thread();        // 创建子进程1的线程
void create_child_pid2_thread();        // 创建子进程2的线程
/*******************************************3、全局变量定义***********************************************/
//全局变量定义
pid_t pid;                      // pid_t被定义为整数类型,用于存储进程ID
int child_pid[3];               // 子进程PID
int i = 0;
int parent_pid = 0;             // 父进程PID
int rc,old_scheduler_policy;    // 进程状态查看
struct sched_param my_params;   // 用以指定目标线程的优先级
char str[10];                               // 用以将整形修改为字符型
char *argv[] = {"kill","-STOP","pid",NULL}; // 用以向终端发送命令
sem_t *Sem_TASK_INTERRUPTIBLE;     // 定义信号量
/*********************************************4、主函数***********************************************/
int main(void)
{
    // 创建信号量
	Sem_TASK_INTERRUPTIBLE = sem_open("mysem", O_CREAT | O_RDWR , 0666, 0);  // 创建名为"Sem_TASK_INTERRUPTIBLE"的信号量
	if (Sem_TASK_INTERRUPTIBLE == SEM_FAILED)
	{
			printf("errno=%d\n", errno);
			return -1;                                                       // 创建失败则返回-1退出
	}
    // 获取进程的PID号,子进程为父进程号+1
    parent_pid = getpid();               
    child_pid[0] = parent_pid+1;
    child_pid[1] = parent_pid+2;
    child_pid[2] = parent_pid+3;
    old_scheduler_policy=sched_getscheduler(0);
    printf("**************************************************\n");
    printf("进程调度策略:\n");
    printf("SCHED_OTHER = %d SCHED_FIFO =%d SCHED_RR=%d \n",SCHED_OTHER,SCHED_FIFO,SCHED_RR);
    printf("*******************进程系统启动*******************\n");
    printf("I'm start parent, pid: %d, ppid: %d,scheduler = %d\n", getpid(), getppid(),old_scheduler_policy);
    // 创建三个子进程
    for(;i < 3;i++)
    {
        creat_child_process(i);     // 调用子进程创建函数
        if (pid==0)                 // 为子进程时
        {
            break;                  // 退出子进程的整个for循环,否则子进程又会继续创建子进程
        }       
    }
    sleep(1);                       // 等待子进程创建完成
    /*******************************************更改进程状态***********************************************/
    // 更改子进程1为实时进程
    if (child_pid[1]==getpid())          
    {
        child1_Process_status_change();
    }
    sleep(1);
    // 更改子进程2为实时进程
    if (child_pid[2]==getpid())
    {
        child2_Process_status_change();
    }
    sleep(1);       //等待子进程状态更改完成
    /*******************************************创建线程***********************************************/
    // 在父进程中创建线程
    if (parent_pid==getpid())                                   // 当处于父进程parent时
    {
        printf("creat thread:\n");
        printf("parent_pid:   主线程tid = %d\n",gettid());       // 串口输出主线程tid
        create_parent_thread();                                 // 调用子线程创建函数
    }
    sleep(1);                                                   
    // 在三个子进程中创建线程
    if (child_pid[0]==getpid())                                 // 当处于子进程child[0]时
    {
        printf("child_pid[0]: 主线程tid = %d\n",gettid());       // 串口输出主线程tid
        create_child_pid0_thread();                             // 调用子线程创建函数
    }
    sleep(1);
    if (child_pid[1]==getpid())                                 // 当处于子进程child[1]时
    {
        printf("child_pid[1]: 主线程tid = %d\n",gettid());       // 串口输出主线程tid
        create_child_pid1_thread();                             // 调用子线程创建函数
    }
    sleep(1);
    if (child_pid[2]==getpid())                                 // 当处于子进程child[2]时
    {
        printf("child_pid[2]: 主线程tid = %d\n",gettid());       // 串口输出主线程tid
        create_child_pid2_thread();                             // 调用子线程创建函数
    }

    sleep(5);
    /*******************************************进程状态切换***********************************************/
    // 将父进程状态切换为:S可中断睡眠
    if (parent_pid==getpid())                                  // 当处于父进程parent时
    {
        printf("Task status switching:\n");
        printf("将父进程 [%d]的进程状态切换为:S可中断睡眠\n",gettid());
        sem_wait(Sem_TASK_INTERRUPTIBLE);                      // 阻塞等待读信号量,使进程状态切换为S可中断睡眠
    }
    sleep(1);
    // 将子进程0状态切换为:D不可中断睡眠
    if (child_pid[0]==getpid())                                 // 当处于子进程child[0]时
    {
        printf("将子进程0[%d]的进程状态切换为:D不可中断睡眠\n",gettid());
        if(!vfork())                                            // 让子进程先运行
        {
            sleep(100);                                         // 睡眠100s          
        }                            
    }
    sleep(1);
    // 将子进程1状态切换为:T暂停状态
    if (child_pid[1]==getpid())                                 // 当处于子进程child[1]时
    {
        printf("将子进程1[%d]的进程状态切换为:T暂停状态\n",gettid());
        sprintf(str,"%d",child_pid[1]);                         // 将PID号从int型转化为字符串char型
        argv[2]=str;                                            // 将需要切换状态的进程PID号写入
        if(execvp("kill",argv) == -1)                           // 在终端中发送命令
        {
            printf("execvp failed!\n");     
        }
    }
    sleep(1);
    // 将子进程2退出:Z退出状态
    if (child_pid[2]==getpid())                                   // 当处于子进程child[2]时
    {
        printf("将子进程2[%d]退出            :Z退出状态\n",gettid());
        exit(0);                                                  // 退出进程
    }

    if (parent_pid==getpid())                                 // 当处于子进程child[0]时
    {
        if(execlp("ps","ps","-aux",NULL) == -1)
        {
            printf("execlp failed!\n");
        }
        printf("after execlp*****\n");
    }
    sleep(100);
    return 0;  
}
/*******************************************5、函数定义*********************************************/
/********************************************创建子进程**********************************************/
/*************************************************************************************************************************
	函  数 : creat_child_process(int i)
	函数名 :  创建子进程
	作  用 : 创建父进程中的子进程child[0]、child[1]、child[2]
*************************************************************************************************************************/
void creat_child_process(int i)
{
    pid = fork();                                           // 子进程中返回子进程的PID号给变量pid
    if(pid == 0)                                            // 该块只在该子进程中执行,写到外面会也到父进程中执行
    {
        old_scheduler_policy=sched_getscheduler(0);         // 参数0:取得当前进程的调度策略
        printf("I'm child_pid[%d], PID: %d, PPID: %d,scheduler = %d\n", i,getpid(),getppid(),old_scheduler_policy);
    }
    else if(pid<0)                                          // 创建失败fork()返回-1
    {
        printf("fork error!");
        exit(1);                                            // 到主调程序,表示异常退出
    }
}
/**********************************************进程状态更改************************************************/
/*************************************************************************************************************************
	函  数 : ×××××_Process_status_change(void)
	函数名 : 进程状态更改
	作  用 : 更改子进程child[1]、child[2]为实时进程
*************************************************************************************************************************/
// 更改子进程1为实时进程
void child1_Process_status_change()
{
    printf("change process status:\n");
    my_params.sched_priority=sched_get_priority_max(SCHED_FIFO);  // 设置进程优先级
    rc=sched_setscheduler(child_pid[1],SCHED_FIFO,&my_params);    // 更改进程状态为SCHED_FIFO
    if(rc<0)                                                      // 如果进程调度失败,返回1
    {  
        perror("set SCHED_FIFO error");
        exit(1);
    }
    old_scheduler_policy=sched_getscheduler(child_pid[1]);        // 获取进程的调度策略
    printf("the child_pid[1]:%d scheduler = %d \n",child_pid[1],old_scheduler_policy); // 串口打印进程状态
}
// 更改子进程2为实时进程
void child2_Process_status_change()
{
    my_params.sched_priority=sched_get_priority_max(SCHED_RR);  // 设置进程优先级
    rc=sched_setscheduler(child_pid[2],SCHED_RR,&my_params);    // 更改进程状态为SCHED_RR
    if(rc<0)                                                    // 如果进程调度失败,返回1
    {  
        perror("set SCHED_FIFO error");
        exit(1);
    }
    old_scheduler_policy=sched_getscheduler(child_pid[2]);      // 获取进程的调度策略
    printf("the child_pid[2]:%d scheduler = %d \n",child_pid[2],old_scheduler_policy); // 串口打印进程状态
}
/********************************************线程创建**********************************************/
// 线程号获取函数
pid_t gettid()
{
     return syscall(SYS_gettid);
}
/*************************************************************************************************************************
	函  数 : ×××××_thread(void)
	函数名 : 子线程的函数体
	作  用 : 定义子线程中执行的代码
*************************************************************************************************************************/
// 父进程子线程体
void *parent_thread()
{
    printf("parent_pid:   子线程tid = %d\n",gettid());    // 获取所属线程号
    pthread_exit(NULL);                                // 线程退出,不关心退出值则参数为:NULL
}
// 子进程0子线程体
void *child_pid0_thread()
{
    printf("child_pid[0]: 子线程tid = %d\n",gettid());  // 获取所属线程号
    pthread_exit(NULL);                                // 线程退出,不关心退出值则参数为:NULLwhile(1)

}
// 子进程1子线程体
void *child_pid1_thread(void *arg)
{
    printf("child_pid[1]: 子线程tid = %d\n",gettid());  // 获取所属线程号
    pthread_exit(NULL);                                // 线程退出,不关心退出值则参数为:NULL
}
// 子进程2子线程体
void *child_pid2_thread()
{
    printf("child_pid[2]: 子线程tid = %d\n",gettid());  // 获取所属线程号
    pthread_exit(NULL);                                // 线程退出,不关心退出值则参数为:NULL
}
/*************************************************************************************************************************
	函  数 : create_×××××_thread(void)
	函数名 : 创建子线程
	作  用 : 创建进程parent、child[0],child[1],child[2]的子线程
*************************************************************************************************************************/
// 创建父进程的子线程
void create_parent_thread()
{
    pthread_t id;                                           // 定义线程的数据结构
    int i = 0;
    pthread_create(&id,NULL,parent_thread,(void*)&i);       // 创建线程,新建线程执行的函数为parent_thread      
    pthread_join(id,NULL);                                  // 等待线程结束
}
// 创建子进程0的子线程
void create_child_pid0_thread()                             
{
    pthread_t id;                                           // 定义线程的数据结构            
    int i = 0;
    pthread_create(&id,NULL,child_pid0_thread,(void*)&i);   // 创建线程,新建线程执行的函数为child_pid0_thread    
    pthread_join(id,NULL);                                  // 等待线程结束
}
// 创建子进程1的子线程
void create_child_pid1_thread()
{
    pthread_t id;                                           // 定义线程的数据结构 
    int i = 0;
    pthread_create(&id,NULL,child_pid1_thread,(void*)&i);   // 创建线程,新建线程执行的函数为child_pid1_thread
    pthread_join(id,NULL);                                  // 等待线程结束
}
// 创建子进程2的子线程
void create_child_pid2_thread()
{
    pthread_t id;                                           // 定义线程的数据结构 
    int i = 0;
    pthread_create(&id,NULL,child_pid2_thread,(void*)&i);   // 创建线程,新建线程执行的函数为child_pid2_thread 
    pthread_join(id,NULL);                                  // 等待线程结束         
}

Linux下多进程多线程的调试 1. Linux下GDB调试常用命令   在调试前明确:在生成源代码的时候加上 -g 选项,开始使用: gdb binFile,退出: ctrl + d 或 quit。下面是调试的常用命令。   list/l 行号:显示binFile源代码,接着上次的位置往下列,每次列10行。   list/l 函数名:列出某个函数的源代码。   r或run:运行程序。   s或step:进行函数调用 阅读详情

相关推荐

用gdb调试单个程序,多线程,多进程

GDB调试程序 在linux中使用gdb调试时我们可以在编译的时候加上-g即可。如果你用一个makefile文件做处理,只需要在里面加上调试信息。gdb调试的是正在运行的程序,而不是我们已经编写好的.c文件。 如果我们没有添加-g,编译完成后我们可以用ls -l 来查看程序的大小,此时main的大小为5000 当我们加上调试信息-g后,我们再用ls -l 来查看main的大小,此时main的大小为6812。 这说明在main程序中,已经添加了我们的一些调试信息 在调试过程中,我们调试需要进行一些操作,以

wu___hao的博客 758

揭秘Linux内核线程切换底层实现

比如线程函数长这样描绘一下场景:在本轮CPU时间片周期内,这个线程执行到i = 1233,这时候发生了时间片到期中断,这个线程就没有机会运行了,需要将CPU时间片让出去,当下次获得调度,能够从i = 1234位置接着运行,而不是从i = 0开始又从头运行什么是线程上下文呢?其实就是程序执行的时候,CPU内部寄存器中的值、线程栈当前使用的位置当发生中断,CPU进入中断处理例程的那一刻,就像给上一个运行的线程拍了张快照,这时候我们将寄存器中的值及线程栈当前使用的位置保存下来,就叫保存上下文。

子牙老师 1522

基于深度学习的中文方言识别模型训练实战

本文介绍了一个基于深度学习的中文方言识别模型开发流程。项目采用PyTorch框架和Chinese-BERT-wwm预训练模型,构建了包含BERT基础层、方言特征增强层和注意力机制的多方言分类系统。文中详细阐述了数据收集策略,包括从社交媒体、语料库和众包平台获取多源数据,并实现了文本清洗、同义词替换和回译等数据增强技术。模型架构部分展示了如何在BERT基础上添加方言特征提取层和多头注意力机制来提升识别性能。该方案支持普通话、粤语等6种主要方言的识别,目标准确率达90%以上,响应时间小于100ms,适用于智能客

电脑管家 1728

linux线程切换怎么实现

用户线程是应用程序中的线程,内核线程则是由操作系统创建和管理的线程。用户线程的调度是由用户空间的调度器完成的,而内核线程的调度则是由内核空间的调度器完成的。然后,操作系统会将另一个线程的上下文加载到CPU中,这个新的线程开始执行,之前的线程则被暂停。选择下一个线程:操作系统的调度器从就绪队列中选择下一个将要执行的线程,并将其上下文从内存中读取到CPU寄存器中。恢复下一个线程的上下文:调度器将下一个线程的上下文从内存中读取到CPU寄存器中,并开始执行新的线程。Linux线程切换的实现涉及到。

qq_45440786的博客 1088

VBA常见错误 - “错误3706,未找到提供程序,该程序可能未正确安装”解决方法

1、问题描述 在利用VBA编程时,引用其它表格数据,出现以下问题: (1)运行“错误3706,未找到提供程序,该程序可能未正确安装”。 (2)引用数据失败 2、解决方法 下载“Access 2010 数据库引擎”,并安装即可。 https://www.microsoft.com/en-us/download/details.aspx?id=54920 AccessDatabaseEngine 2010 官方安装包,官网下载不了的可以来这里下载。(1)运行“错误3706,未找到提..

Nemuel的博客 3万+

手把手教你用gym训练宇树GO2机器人模型(附完整配置文件)

本文提供了一份详细的实战指南,教你如何使用Gym框架为宇树GO2四足机器人搭建强化学习训练环境。文章深入解析了环境配置、参数调试、奖励函数设置等关键步骤,并分享了避开常见陷阱的经验,旨在帮助开发者高效完成模型训练。

oo7890的博客 321

浅谈pthread_setschedparam()和sched_setscheduler()的使用

pthread_setschedparam() 转自:https://blog.youkuaiyun.com/hello_wyq/article/details/1557707,作者:hello_wyq int pthread_setschedparam(pthread_t target_thread,intpolicy,conststruct sched_param *par...

RosyCloudsLee的博客 2559

伪距单点定位算法原理以及利用最小二乘法计算实例

即该公式:建立下列代价函数满足最佳估值的条件为:即:可解得未知参数 X 的最佳估值由于每个可见卫星观测量的精度可能不一样,这时,需要对不同观测量赋予一个权重系数,称为加权。

qq_43381998的博客 1万+

【linux】进程和线程的几种状态及状态切换

进程和线程的状态

qq_66314292的博客 5657

Qt 5.9.1 32位下,手把手搞定周立功CAN二次开发库的加载与配置(含常见错误排查)

本文详细介绍了在Qt 5.9.1 32位环境下配置周立功CAN二次开发库的完整流程,包括环境准备、项目配置、常见错误排查及性能优化建议。特别针对MinGW 32bit环境,提供了.pro文件的精准配置和DLL部署策略,帮助开发者快速解决库文件匹配、编译报错和运行时问题,实现高效的CAN总线通信开发。

weixin_28717431的博客 356

u-boot-2014.10移植第22天----添加nand flash命令支持(四)

解决问题:nand0: MTD Erase failure: -5 drivers/mtd/nand/nand_bbt.c文件中初始化bbt/* * Allocate memory (2bit per block) and clear the memory bad block * table. */ this->bbt = kzalloc(len, GFP_

fulinux的博客 3631

getpid、gettid、getgid

getpid: 说明:getpid返回当前进程标识,getppid返回父进程标识。 使用方法: 头文件: #include <sys/types.h> #include <unistd.h> 函数原型: pid_t getpid(void); pid_t getppid(void); gettid:获取线程ID,并不是现成接口,而是自己实现的。 实现方式: #include <sys/syscall.h> pid_t gettid(void)

m0_59666413的博客 4500

[ vulhub漏洞复现篇 ] ActiveMQ反序列化漏洞复现(CVE-2015-5254)

Apache ActiveMQ是美国阿帕奇(Apache)软件基金会所研发的一套开源的消息中间件,它支持Java消息服务、集群、Spring Framework等。由于ActiveMQ是一个纯Java程序,因此只需要操作系统支持Java虚拟机,ActiveMQ便可执行。Apache ActiveMQ 5.13.0之前5.x版本中存在安全漏洞,该漏洞源于程序没有限制可在代理中序列化的类。......

qq_51577576的博客 4444

XV6源代码阅读-进程线程

文章目录Exercise1 源代码阅读Exercise2 带着问题阅读参考文献 Exercise1 源代码阅读 基本头文件:types.h param.h memlayout.h defs.h x86.h asm.h mmu.h elf.h types.h:仅仅是定义uint, ushort, uchar pde_t别名; typedef unsigned int uint; type...

荒野之萍 3617

数据分享:中国历年省、市、县行政区划shp(1949~2023年共计75年)

中华人民共和国县级以上行政区沿革》(三册,1949-1983年)“The Atlas of Changes of Administrative Regions of China”;《中华人民共和国行政区划沿革地图集》The yearly publications of “The Administrative Regions”, 1985-2014;每年的出版行政区划简册(1985-2014年)行政区划网:www.xzqh.org。行政区划网:www.xzqh.org。

J_Giser的博客 3685

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

每线程对应1vcpu_02.进程与线程

我们常看到书上写进程是操作系统分配资源的基本单元,线程是CPU执行的基本单位。进程:通俗来讲,就是运行的程序。线程:就是在进程的基础上,将进程划分为更小的任务,他们共享进程的资源。 首先来谈谈进程,在操作系统中,我们来做一件大家想必都做过的事情,我们在窗口命令行中运行HelloWord程序。当我们打开cmd窗口时,这个交互式窗口进程开启,运行javac HelloWorld.java...

weixin_42520909的博客 492

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

【操作系统】总结篇

【操作系统】常见问题及解答

m0_51913750的博客 1019

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

【嵌入式软件工程师面经】Linux多进程与多线程

准备多线程和多进程的面试问题时,深入理解每个问题的核心概念以及它们在实际系统中的应用是非常重要的。实际场景中的问题通常比理论上更为复杂,因此理解如何在特定的上下文中应用这些概念至关重要,当准备这类面试问题时,最好的方法是结合理论知识与实践经验,尝试举一些实际应用中的例子来展示你如何解决多线程和多进程相关的问题。此外,理解Linux内核的工作原理和相关的系统调用也非常重要

嵌入式技术开发 2253

多线程多进程

进程(独立执行单元、资源分配的基本单位),线程(进程中的一个执行单元),进程上下文切换。进程间通信:文件、Socket通信、管道、消息队列;线程间通信:事件、条件变量、读写锁。进程创建:fork;线程创建:继承 Thread 类或实现 Runnable 接口。sleep()是Thread类的方法,不释放锁;wait() 是Object类的方法,会释放锁。

qq_53631388的博客 1120

Linux(多进程与多线程)

多线程 多进程

qq_57594025的博客 2048

【Linux的线程篇章 - 线程、进程、多线程、多进程等知识】

Linux学习笔记017 -- Linux的线程篇章 - 线程、进程、多线程、多进程等知识

m0_69455439的博客 1377

【Linux】gdb调试多线程与多进程

前言 在多线程编程时,当我们需要调试时,有时需要控制某些线程停在断点,某些线程继续执行。有时需要控制线程的运行顺序。有时需要中断某个线程,切换到其他线程。这些都可以通过gdb实现。 下图为多线程与多进程调试的通用常用命令,应该熟练掌握下面几种命令的使用。 gdb调试多线程 多线程调试的主要任务是准确及时地捕捉被调试程序线程状态的变化的事件,并且GDB针对根据捕捉到的事件做出相应的操作,其实最终的...

码农印象 1702

Linux 多进程 .之多进程,多线程的概念和区别,进程线程的调度,状态关系(一)

无论执行哪个进程,另一个进程肯定是不被执行,程序自然就是无运行的状态。一个基本的事实前提:单核CPU在一个瞬间只能处理一个任务,就像人只有一张嘴,不能吃饭的同时,又说话,又唱歌,有人抬杠,不是同时进行的吗,说话时声带振动,吃饭吞咽时,是不可以声带振动的,不然会被噎死。所谓的进程上下文,就是一个进程在执行的时候,CPU的所有寄存器中的值、进程的状态以及堆栈上的内容,当内核需要切换到另一个进程时,它 需要保存当前进程的所有状态,即保存当前进程的进程上下文,以便再次执行该进程时,能够恢复切换时的状态,继续执行。

rjszcb的博客 946

Linux --- 线程 之 线程与多线程 (进程与线程,多进程与多线程的区别)

【操作系统】--- 进程与线程 和 多进程和多线程的区别 以及 线程的相关接口介绍与操作

qq_56674342的博客 908

Linux多进程与多线程

认识冯诺依曼体系结构;简单认识操作系统;进程概念(进程状态/优先级/环境变量/进程调度);进程控制(僵尸进程/孤儿进程);多进程 VS 多线程;进程地址空间

qq_41906009的博客 544

linux多进程与多线程总结

2 linux多进程与多线程2.1 进程间通信2.1.1 管道2.1.2 信号2.1.3 消息队列2.1.4 共享内存3 线程4 IO多路复用4.1 非阻塞IO4.2 IO多路复用。

谁家的喵 1702
上一篇: 侯杰C++ 面向对象高级开发—学习心得和笔记
下一篇: Linux多进程、线程间通信:共享内存、信号量、管道、互斥锁
ZHU~.
博客等级 码龄7年 193粉丝 24原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值