Linux-线程

【Linux】线程 Linux线程的基础知识 阅读详情

进程 与 线程:

参考自: Linux多线程编程初探 - 峰子_仰望阳光 - 博客园 (cnblogs.com)

进程:
  典型的UNIX/Linux进程可以看成只有一个控制线程:一个进程在同一时刻只做一件事情。
有了多个控制线程后,在程序设计时可以把进程设计成在同一时刻做不止一件事,每个线程各自处理独立的任务。  

  进程是程序执行时的一个实例,是担当分配系统资源(CPU时间、内存等)的基本单位。
在面向线程设计的系统中,进程本身不是基本运行单位,而是线程的容器。
程序本身只是指令、数据及其组织形式的描述,进程才是程序(那些指令和数据)的真正运行实例。// 程序是静态概念,进程是动态概念
 

线程:
    线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。进程的所有信息对该进程的所有线程都是共享的,包括可执行的程序文本、程序的全局内存和堆内存、栈以及文件描述符。

二者联系:
 进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。
线程有自己的堆栈和局部变量,但线程没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。

二者区别:
  总的来说就是:进程有独立的地址空间,线程没有单独的地址空间(同一进程内的线程共享进程的地址空间)

使用线程理由:
 1.和进程相比,它是一种非常 "节俭" 的多任务操作方式。省内存,切换效率高
    2.线程间方便的通信机制 // 共享数据,方便线程间的通信 --(同一进程内的线程共享进程的地址空间)

"进程——资源分配的最小单位,线程——程序执行的最小单位"  


Linux线程开发API:

多线程开发的最基本概念主要包含三点:线程,互斥锁,条件  3 + 4 + 5

线程操作又分线程的创建,退出,等待 3 种

互斥锁则包括 4 种操作,分别是创建,销毁,加锁和解锁。

条件操作有 5 种操作:创建,销毁,触发,广播和等待。


线程:


1. 线程创建


#include <pthread.h>
int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*start_rtn)(void *), void *restrict arg);

// 返回:若成功返回0,否则返回错误编号


 2. 线程退出

  单个线程可以通过以下三种方式退出,在不终止整个进程的情况下停止它的控制流:

  1)线程只是从启动例程中返回,返回值是线程的退出码。

  2)线程可以被同一进程中的其他线程取消。

  3)线程调用pthread_exit:

#include <pthread.h>
int pthread_exit(void *rval_ptr);


3. 线程等待

#include <pthread.h>
int pthread_join(pthread_t thread, void **rval_ptr);
// 返回:若成功返回0,否则返回错误编号
pthread_t pthread_self(void);
// 返回:调用线程的ID

case1:while来等待


#include <pthread.h>
#include <stdio.h>


// int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*start_rtn)(void *), void *restrict arg);

void *func1(void *arg)
{//获取当前线程ID
    printf("thread1: %ld pthread create.\n",(unsigned long)pthread_self());
    printf("thread1: param is %d\n",*((int *)arg));
}

int main()
{
    pthread_t thread1;
    int arg = 100;
    int pret;

 //创建线程1-thread1,调用函数func1,传递参数arg,NULL 创建默认属性打的线程
    pret = pthread_create(&thread1, NULL, func1, (void *)(&arg));
    if(!pret){//进程创建成功返回0
    puts("create success.");
    }
    else {//失败返回-1
        puts("create failed.");
    }
   printf("main: %ld .\n",(unsigned long)pthread_self());// 获取main函数的线程ID
    while(1); // 不加的话,主线程会没创建完线程就退出

    return 0;
}
========================================
 

case2:结合等待退出的API来调用:


#include <pthread.h>
#include <stdio.h>


// int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*start_rtn)(void *), void *restrict arg);
// int pthread_exit(void *rval_ptr);
// int pthread_join(pthread_t thread, void **rval_ptr);
void *func1(void *arg)
{
    //static int pret=88; //static 保护pret退出这个函数不被销毁
     static char * p="this is run out."; // 返回字符串

    printf("thread1: %ld pthread create.\n",(unsigned long)pthread_self());
    printf("thread1: param is %d\n",*((int *)arg));
   // pthread_exit((void*)&pret);
// 线程退出 -- 里面的参数 -- 线程退出状态 -- 自己设计,可以是int 也可以是char*
 pthread_exit((void*)p); // 返回字符串
}

int main()
{
    pthread_t thread1;
   // int* pthr=NULL;
 char* pthr=NULL;  // 接收返回的字符串
    int arg = 100;
    int pret;
    pret = pthread_create(&thread1, NULL, func1, (void *)(&arg)); //arg --参数传递
    if(!pret){
    puts("create success.");
    
    }
    else {
        puts("create failed.");
    }
   printf("main: %ld .\n",(unsigned long)pthread_self());
    // 等待线程thread1退出(线程没退出phread_exit就会阻塞),第二个参数收回线程的退出

  状态,NULL--不收回
    pthread_join(thread1,(void**)&pthr); // 指针再取地址达到二级指针类型才能强制装换位二级指针
    //printf("thread quit id:%d\n",*pthr);// 查看指针拿到的退出数据
   printf("thread quit id:%s\n",pthr);// 输出进程退出返回值,字符串名就是指针
    return 0;
}
========================================
 

case3: 线程共享内存验证:


#include <pthread.h>
#include <stdio.h>
#include<unistd.h>

// int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*start_rtn)(void *), void *restrict arg);
int g_data=0;// 共享变量
void *func1(void *arg)
{
    printf("thread1: %ld pthread create.\n", (unsigned long)pthread_self());
    printf("thread1: param is %d\n", *((int *)arg));
    while(1){
        printf("thread1:  %d\n",g_data++);
        sleep(1);
    }
  //  pthread_exit(NULL);
}
void *func2(void *arg)
{
    printf("thread2: %ld pthread create.\n", (unsigned long)pthread_self());
    printf("thread2: param is %d\n", *((int *)arg));
     while(1){
        printf("thread2:  %d\n",g_data++);
        sleep(1);
    }
   // pthread_exit(NULL);
}

int main()
{
    pthread_t thread1;
    pthread_t thread2;
    int arg = 100;
    int pret;
    pret = pthread_create(&thread1, NULL, func1, (void *)(&arg));
    if (!pret)
    {
        puts("main:create thread1 success.");
    }
    else
    {
        puts("main:create  thread1 failed.");
    }

    pret = pthread_create(&thread2, NULL, func2, (void *)(&arg));
    if (!pret)
    {
        puts("main:create thread2 success.");
    }
    else
    {
        puts("main:create thread2 failed.");
    }
     while(1){
        printf("main:  %d\n",g_data++);
        sleep(1);
    }
    pthread_join(thread1, NULL);
    pthread_join(thread2, NULL);
    printf("main: %ld .\n", (unsigned long)pthread_self());
;

    return 0;
}
==============================

输出结果中,我们发现在func1,func2,main函数三个线程中,g_data的数据时不重样且递增的,什么我们的线程共享了进程分配到的内存


 

互斥锁API的使用:

概念:
 互斥量(mutex)从本质上来说是一把锁,在访问共享资源前对互斥量进行加锁,在访问完成后释放互斥量上的锁

1. 创建及销毁互斥锁

#include <pthread.h>
int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);
int pthread_mutex_destroy(pthread_mutex_t mutex);
// 返回:若成功返回0,否则返回错误编号
 要用默认的属性初始化互斥量,只需把attr设置为NULL。

2. 加锁及解锁

#include <pthread.h>
int pthread_mutex_lock(pthread_mutex_t mutex);
int pthread_mutex_trylock(pthread_mutex_t mutex);
int pthread_mutex_unlock(pthread_mutex_t mutex);
// 返回:若成功返回0,否则返回错误编号


 上锁后,只有在锁里面的代码执行完后才解锁,解锁前不会去调用其他进程
互斥量就是一把锁,对锁有上锁和解锁操作,这两个操作之间的代码叫共享资源,没执行完共享资源进程前,
其他进程不能调用,执行完后,其他进程可以去争抢这把锁,第一个争抢到的进程又能上锁,解锁, 这样就保证了
我们的进程是一个线程一个线程的执行,在没有执行完单曲线程之前不会去执行其他线程

case1: 互斥锁应用


#include <pthread.h>
#include <stdio.h>
#include<unistd.h>

// int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*start_rtn)(void *), void *restrict arg);
int g_data=0;// 共享变量
pthread_mutex_t mutex;
void *func1(void *arg)
{
    int i;

    // 上锁 -- 然后后续想要再上这把锁mutex 就会被阻塞,直到这把锁被解锁,保证了上锁解锁里面的函数快能执行完,才去执行其他进程,保证进程执行的时候不受打扰
    pthread_mutex_lock(&mutex);
    for(i=0;i<3;++i)
    {
    printf("thread1: %ld pthread create.\n", (unsigned long)pthread_self());
    printf("thread1: param is %d\n", *((int *)arg));
    sleep(1);
    }

//解锁
    pthread_mutex_unlock(&mutex);
  //  pthread_exit(NULL);
}
void *func2(void *arg)
{
    pthread_mutex_lock(&mutex); // 进程1没开锁你上不了锁,阻塞在这里
    printf("thread2: %ld pthread create.\n", (unsigned long)pthread_self());
    printf("thread2: param is %d\n", *((int *)arg));
    pthread_mutex_unlock(&mutex);
   // pthread_exit(NULL);
}

int main()
{
    pthread_t thread1;
    pthread_t thread2;

    int arg = 100;
    int pret;
    //int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);
    // 初始化我们的互斥🔓
    pthread_mutex_init(&mutex,NULL);

    pret = pthread_create(&thread1, NULL, func1, (void *)(&arg));
    if (!pret)
    {
        puts("main:create thread1 success.");
    }
    else
    {
        puts("main:create  thread1 failed.");
    }

    pret = pthread_create(&thread2, NULL, func2, (void *)(&arg));
    if (!pret)
    {
        puts("main:create thread2 success.");
    }
    else
    {
        puts("main:create thread2 failed.");
    }

    pthread_join(thread1, NULL);
    pthread_join(thread2, NULL);
    printf("main: %ld .\n", (unsigned long)pthread_self());
    pthread_mutex_destroy(&mutex);//销毁互斥锁
    while (1);
   

    return 0;
}
==================================
 

case2: 互斥锁 实现对共享资源的访问:


让g_data在thread1中加到3在退出,or去执行其他进程,main函数里面没上锁就能访问
进程是线程的容器,线程可以控制进程的退出

#include <pthread.h>
#include <stdio.h>
#include<unistd.h>
#include<stdlib.h>

// int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*start_rtn)(void *), void *restrict arg);
int g_data=0;// 共享变量
pthread_mutex_t mutex;
void *func1(void *arg)
{

    printf("thread1: %ld pthread create.\n", (unsigned long)pthread_self());
    printf("thread1: param is %d\n", *((int *)arg));
    
    pthread_mutex_lock(&mutex);//先让下面循环里的代码执行完,再解锁
    for(;;)
    {
    printf("thread1:%d\n",g_data++);
    sleep(1);
    if(g_data==3){
      pthread_mutex_unlock(&mutex); //用完解锁
      puts("------------thread1 quit-----------------------");
      //pthread_exit(NULL);
      exit(0);
      }

    }
   
  //  pthread_exit(NULL);
}
void *func2(void *arg)
{


    
    printf("thread2: %ld pthread create.\n", (unsigned long)pthread_self());
    printf("thread2: param is %d\n", *((int *)arg));
    
    for(;;)
    {
    printf("thread2:%d\n",g_data);
    pthread_mutex_lock(&mutex); // 由于进程1没有解锁,他就会阻塞再这里上不了锁
    g_data++;
    pthread_mutex_unlock(&mutex);
    sleep(1);
    }
   
   // pthread_exit(NULL);
}

int main()
{
    pthread_t thread1;
    pthread_t thread2;
    int arg = 100;
    int pret;
    //int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);
    // 初始化🔓
    pthread_mutex_init(&mutex,NULL);
    pret = pthread_create(&thread1, NULL, func1, (void *)(&arg));
    if (!pret)
    {
        puts("main:create thread1 success.");
    }
    else
    {
        puts("main:create  thread1 failed.");
    }

    pret = pthread_create(&thread2, NULL, func2, (void *)(&arg));
    if (!pret)
    {
        puts("main:create thread2 success.");
    }
    else
    {
        puts("main:create thread2 failed.");
    }
    printf("main: %ld .\n", (unsigned long)pthread_self());
    while(1){
    printf("main: g_data=%d\n",g_data);
    sleep(1);

    }
   
    pthread_join(thread1, NULL);
    pthread_join(thread2, NULL);
    
    pthread_mutex_destroy(&mutex); //线程全部退出后销毁🔓
  

    return 0;
}

==========================


配置测试文件测试;


1).sh文件  -- shell 脚本测试

vi test.sh
//添加3个./a.out
chmod -x test.sh
// 给test可执行的权限
./test --执行三次./a.out 来测试

2).c文件使用system测试

int main()
{
  int k=3;
  while(k--){
  system("./a.out");

  }

    return 0;
}

=========================================


死锁

什么情况下回死锁:


pthread_mutex_t mutex;
pthread_mutex_t mutex2;
void *func1(void *arg)
{
   
    pthread_mutex_lock(&mutex);
    sleep(3);
    pthread_mutex_lock(&mutex2);    

     int i;
    for(i=0;i<3;++i)
    {
    printf("thread1: %ld pthread create.\n", (unsigned long)pthread_self());
    printf("thread1: param is %d\n", *((int *)arg));
    sleep(1);
    }
    pthread_mutex_unlock(&mutex);
  //  pthread_exit(NULL);
}
void *func2(void *arg)
{
    pthread_mutex_lock(&mutex2);
    sleep(3);
    pthread_mutex_lock(&mutex);    

    printf("thread2: %ld pthread create.\n", (unsigned long)pthread_self());
    printf("thread2: param is %d\n", *((int *)arg));
    pthread_mutex_unlock(&mutex);
   // pthread_exit(NULL);
}
前提2个锁:


具体:
上面这种情况就会造成死锁,进程1拿到锁1,sleep(3),期间进程2拿到锁2,sleep(3),进程1一直拿不到锁2被进程2拿走
造成了阻塞,同理,之后进程2也拿不到锁1, 这就成为了死锁


通用:
两个线程都拿到一个锁,而且都不解锁,但是都想去拿另一个锁(拿不到,被另一个线程拿走了),导致一直阻塞,造成死锁

=========================================


条件API


 1. 创建及销毁条件变量

#include <pthread.h>
int pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr);
int pthread_cond_destroy(pthread_cond_t cond);
// 返回:若成功返回0,否则返回错误编号
  除非需要创建一个非默认属性的条件变量,否则pthread_cont_init函数的attr参数可以设置为NULL。

  2. 等待

#include <pthread.h>
int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex);
int pthread_cond_timedwait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, cond struct timespec *restrict timeout);
// 返回:若成功返回0,否则返回错误编号
  pthread_cond_wait等待条件变为真。如果在给定的时间内条件不能满足,那么会生成一个代表一个出错码的返回变量。传递给pthread_cond_wait的互斥量对条件进行保护,调用者把锁住的互斥量传给函数。函数把调用线程放到等待条件的线程列表上,然后对互斥量解锁,这两个操作都是原子操作。这样就关闭了条件检查和线程进入休眠状态等待条件改变这两个操作之间的时间通道,这样线程就不会错过条件的任何变化。pthread_cond_wait返回时,互斥量再次被锁住。

  pthread_cond_timedwait函数的工作方式与pthread_cond_wait函数类似,只是多了一个timeout。timeout指定了等待的时间,它是通过timespec结构指定。

  3. 触发

#include <pthread.h>
int pthread_cond_signal(pthread_cond_t cond);
int pthread_cond_broadcast(pthread_cond_t cond);
// 返回:若成功返回0,否则返回错误编号
  这两个函数可以用于通知线程条件已经满足。pthread_cond_signal函数将唤醒等待该条件的某个线程,而pthread_cond_broadcast函数将唤醒等待该条件的所有进程
线程控制实现线程的同步:

case:通过条件控制g_data在进程2加到3再到进程1操作一次恢复,重新让进程2操作

#include <pthread.h>
#include <stdio.h>
#include<unistd.h>
#include<stdlib.h>

// int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*start_rtn)(void *), void *restrict arg);
int g_data=0;// 共享变量
pthread_mutex_t mutex;
pthread_cond_t cond;// 定义条件变量

void *func1(void *arg)
{

    printf("thread1: %ld pthread create.\n", (unsigned long)pthread_self());
    printf("thread1: param is %d\n", *((int *)arg));
    
   
    for(;;)
    {
     pthread_cond_wait(&cond,&mutex);//等待条件发生 -- signal触发
 
      puts("------------thread1-----------------------");
      //pthread_exit(NULL);
   
      
       printf("thread1:%d\n",g_data++);
     
       g_data=0;
        sleep(1);

    }
   
  //  pthread_exit(NULL);
}
void *func2(void *arg)
{


    
    printf("thread2: %ld pthread create.\n", (unsigned long)pthread_self());
    printf("thread2: param is %d\n", *((int *)arg));
    
    for(;;)
    {
    printf("thread2:%d\n",g_data);
    pthread_mutex_lock(&mutex); // 上锁,保证,上锁解锁间的代码块能完整执行
    g_data++;
    if(g_data==3){
    pthread_cond_signal(&cond);//单次唤醒wait,这时候func里面的wait触发就会往下执行

    }
    pthread_mutex_unlock(&mutex);
    sleep(1);
    }
   
   // pthread_exit(NULL);
}

int main()
{
    pthread_t thread1;
    pthread_t thread2;
    int arg = 100;
    int pret;
    //int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);
    pthread_cond_init(&cond,NULL); //创造条件变量
    // 初始化🔓
    pthread_mutex_init(&mutex,NULL);
    pret = pthread_create(&thread1, NULL, func1, (void *)(&arg));
    if (!pret)
    {
      //  puts("main:create thread1 success.");
    }
    else
    {
        puts("main:create  thread1 failed.");
    }

    pret = pthread_create(&thread2, NULL, func2, (void *)(&arg));
    if (!pret)
    {
       // puts("main:create thread2 success.");
    }
    else
    {
        puts("main:create thread2 failed.");
    }
    printf("main: %ld .\n", (unsigned long)pthread_self());
    while(1){
   // printf("main: g_data=%d\n",g_data);
    sleep(1);

    }
   
    pthread_join(thread1, NULL);
    pthread_join(thread2, NULL);
    pthread_cond_destroy(&cond);// 销毁条件变量
    pthread_mutex_destroy(&mutex); //线程全部退出后销毁🔓
  

    return 0;
}


================================
 测试常用: 在指令执行后 & --后台运行。比如 ./a.out &


====================================


case2:使用宏来静态初始化:

#include <pthread.h>
#include <stdio.h>
#include<unistd.h>
#include<stdlib.h>

// int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*start_rtn)(void *), void *restrict arg);
int g_data=0;// 共享变量
//使用宏来静态初始化
pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond=PTHREAD_COND_INITIALIZER;

void *func1(void *arg)
{
    static int cnt=0;
    printf("thread1: %ld pthread create.\n", (unsigned long)pthread_self());
    printf("thread1: param is %d\n", *((int *)arg));
    
   
    for(;;)
    {
     pthread_cond_wait(&cond,&mutex);//等待条件发生 -- signal触发
 
      puts("------------thread1-----------------------");
      //pthread_exit(NULL);
   
      
      printf("thread1:%d\n",g_data);
       g_data=0;
        sleep(1);
        if(cnt++ ==10){
            exit(1);
        }

    }
   
  //  pthread_exit(NULL);
}
void *func2(void *arg)
{


    
    printf("thread2: %ld pthread create.\n", (unsigned long)pthread_self());
    printf("thread2: param is %d\n", *((int *)arg));
    
    for(;;)
    {
    printf("thread2:%d\n",g_data);
    pthread_mutex_lock(&mutex);
    g_data++;
    if(g_data==3){
    pthread_cond_signal(&cond);//单次唤醒wait

    }
    pthread_mutex_unlock(&mutex);
    sleep(1);
    }
   
   // pthread_exit(NULL);
}

int main()
{
    pthread_t thread1;
    pthread_t thread2;
    int arg = 100;
    int pret;
    //动态初始化  ,对应宏是静态初始化
    //int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);
   // pthread_cond_init(&cond,NULL); //创造条件变量
    // 初始化🔓
   // pthread_mutex_init(&mutex,NULL);
    pret = pthread_create(&thread1, NULL, func1, (void *)(&arg));
    if (!pret)
    {
      //  puts("main:create thread1 success.");
    }
    else
    {
        puts("main:create  thread1 failed.");
    }

    pret = pthread_create(&thread2, NULL, func2, (void *)(&arg));
    if (!pret)
    {
       // puts("main:create thread2 success.");
    }
    else
    {
        puts("main:create thread2 failed.");
    }
    printf("main: %ld .\n", (unsigned long)pthread_self());
    while(1){
   // printf("main: g_data=%d\n",g_data);
    sleep(1);

    }
   
    pthread_join(thread1, NULL);
    pthread_join(thread2, NULL);
    pthread_cond_destroy(&cond);// 销毁条件变量
    pthread_mutex_destroy(&mutex); //线程全部退出后销毁🔓
  

    return 0;
}

微信小程序 - 真机调试调用接口报错{errno: 600001, errMsg: “request:fail -102:net::ERR_CONNECTION_REFUSED},真机运行测试请求异常 微信小程序,真机,调试测试,运行报错,API接口,服务器接口都报错了,小程序报错errno: 600001,小程序报错request:fail -102:net::ERR_CONNECTION_REFUSED,真实手机打开接口全都失效了,微信小程序真机测试失败,微信小程序{errno: 600001, errMsg: "request:fail -102:net::ERR_CONNECTION_REFUSED"},详细解决方法,https,服务器SSL证书,无法解决,服务器更换SSL证书,接口地址改了也不行 阅读详情

相关推荐

colmap+openMVS稠密重建

简要记录一下colmap+openMVS稠密重建相关使用。

weixin_41631106的博客 2243

4.linux_线程编程

linux_线程编程

qq_41682371的博客 370

DeepSeek + 番茄小说:AI辅助小说开发最全指南

DeepSeek与番茄小说合作推出AI辅助小说创作系统,通过DeepSeek的文本生成能力(包括情节构建、角色塑造等)结合番茄小说的市场数据,为作者提供从创意到发布的全流程支持。系统包含智能创意生成器、角色设计、章节自动生成等核心模块,采用数据驱动优化策略,支持128K长文本处理和多风格模仿。开发架构采用Python+FastAPI技术栈,提供分层审核机制确保质量。该系统可帮助作者突破创作瓶颈,提升效率,同时提供订阅制、内容分成等多元变现模式。需注意版权问题和原创性保证。

weixin_41445009的博客 1677

Linux线程初识

什么是线程 1、一个程序中的多个执行路线就叫线程(thread),线程是一个进程内部的一个控制序列。 2、典型的UNIX/Linux进程可以看成只有一个控制线程:一个进程在同一时刻只做一件事情。有了多个控制线程后,在程序设计时可以把进程设计成在同一时刻做不止一件事,每个线程各自处理独立的任务。 线程有进程的关系 1、事实上,所有的进程都至少有一个执行线程。 2、进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。 3、进程不是基本的运行单位,而是线程

m0_50202012的博客 279

5.4 磁悬浮轴承控制系统仿真:在MATLAB/Simulink中搭建包含功放、传感器模型的闭环系统模型,进行稳定性与动态性能仿真

磁悬浮轴承控制系统仿真方法 摘要:磁悬浮轴承控制系统仿真需建立包含转子动力学、传感器、控制器、功率放大器和电磁执行器的高保真非线性模型。通过MATLAB/Simulink搭建闭环系统,重点建模传感器带宽限制与噪声、功放饱和特性以及电磁力非线性。仿真分析包括时域阶跃响应、扰动抑制测试,频域稳定性分析(伯德图、奈奎斯特图),以及参数摄动下的鲁棒性验证。关键要验证控制算法在非线性因素影响下的稳定性和动态性能,为实际系统实现提供可靠依据。仿真中需特别注意物理量单位一致性和数字控制离散化效应。

技术工作者 1108

PyMOL下载安装教程(附安装包)2025最新版(PyMOL 3.0.3)

本文详细介绍了Windows系统下PyMOL分子建模软件的安装教程。主要内容包括:提供安装包下载链接,强调需关闭杀毒软件;分步骤讲解管理员身份运行安装程序、接受协议、选择安装路径等安装流程;重点说明如何配置隐藏文件夹ProgramData中的许可证文件;最后提供基础使用技巧和常见问题解决方案。该教程适用于需要制作高质量分子结构图的科研人员和新手用户,帮助完成软件部署并顺利开展工作。

progalchemist的博客 3804

Linux系统编程_线程

Linux系统编程线程

chmod_a的博客 155

LAMMPS-使用MATLAB计算径向分布函数

首先需要使用LAMMPS进行分子动力学模拟,并获取到所需的数据文件,LAMMPS是一款开源的分子动力学模拟软件,可以模拟原子、分子和离子的运动行为,对于本文的目标假设你已经完成了LAMMPS的安装和模拟过程,获得了数据文件。)是一种重要的统计工具,用于描述原子或分子之间的空间分布情况,通过计算RDF可以获得物质的结构信息、相互作用距离以及相位转变等重要参数,本文将介绍如何使用MATLAB计算LAMMPS生成的数据文件的径向分布函数。变量替换为你的实际数据文件的名称。

weixin_50547796的博客 515

Linux之线程

和多进程相比,多线程是一种比较节省资源的多任务操作方式。启动一个新的进程必须分配给它独立的地址空间,每个进程都有自己的堆栈段和数据段,系统开销比较高,进行数据的传递只能通过进行间通信的方式进行。在同一个进程中,可以运行多个线程,运行于同一个进程中的多个线程,它们彼此之间使用相同的地址空间,共享全局变量和对象,启动一个线程所消耗的资源比启动一个进程所消耗的资源要少。.........

hello 2381

AEJoy —— 表达式之仅限在某一维摆动【JS】

效果图 wiggle() 的作用仅限于水平方向 想法 wiggle() 确实是一个非常方便的工具,但有时您希望对它有更多的控制。在本例中,我们希望仅将摆动限制在水平方向。 设计 要理解 wiggle() 最重要的一点是,它生成的结果与应用它的属性具有相同的维度。例如,如果你将 wiggle() 应用于 3D 层的 position 属性,结果将是一个由三个元素组成的数组(x、y 和 z 各一个)。我们需要做的就是将 wiggle() 的结果捕捉到一个变量(我们称之为 “w” ),然后从这个变量中提取我们想

ShaderJoy 的兴趣技术杂货铺 2094

基于STM32设计的环境监测系统(华为云IOT)_300

随着空气污染问题日益严峻,环境空气质量的监测变得愈加重要。为了解决这一问题,本项目设计并实现了一款基于STM32的空气质量监测设备,能够实时监测空气中的温湿度、二氧化碳浓度和甲醛浓度,并通过OLED显示屏展示数据。此外,设备支持通过WIFI模块将数据上传至云端,用户可以通过手机APP或Windows上位机查看实时数据。设备采用MQTT协议与华为云IOT物联网服务器进行数据通信,确保数据的实时性和可靠性。本项目还结合了低功耗设计和高灵敏度传感器,使得设备能够高效稳定地运行,并实现远程监控功能。

696

Linux线程学习笔记

线程相关学习:线程、互斥锁、条件

wantc的博客 230

RK3568移植AP6256

本文主要是记录RK3568移植正基的AP6256的WIFIBT模块,感兴趣的朋友可以一起学习!!!提示:以下是本篇文章正文内容,下面案例可供参考。

qq_24093081的博客 3715

【Linux】Linux线程概念和线程控制

本文介绍了Linux中线程的概念和线程控制--线程创建,终止,等待,分离

qq_67582098的博客 2602

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

【Linux线程】Linux线程编程基础:概念、创建与管理

在当今的软件开发领域,多线程编程已经成为了一种不可或缺的技术。特别是在Linux操作系统环境下,多线程编程更是被广泛地应用于各种高性能、高并发的应用场景中。然而,多线程编程也是一项极具挑战性的任务,它要求开发者具备扎实的编程基础,对并发控制、资源管理等有深入的理解

EterNity_TiMe_的计算机学习之路 3625

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

Linux:线程概念 | 线程控制

当CPU调度执行该“”进程“时,只会执行原本进程中的一部分代码和数据,执行我们要执行任务的一部分任务,我们将这种比传统“进程”更加轻量化的进程就称为线程!)下,其中一些线程抢占锁的能力是非常强的,导致其他线程长时间无法获得锁资源,导致线程饥饿问题。我们也将这种线程称为轻量级进程!在Linux中,如果操作系统真的支持线程,此时在计算机中必然存在大量的线程,所以OS需要对线程进行管理。如果不关心线程的返回值,join是一种负担,这个时候,我们可以将线程设置为分离状态,告诉系统,当线程退出时,自动释放线程资源!

Zhenyu_Coder的博客 2506

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

【Linux】线程详解

在一个程序里的一个执行路线就叫做线程。更准确的定义是:线程是“一个进程内部的控制序列”一切进程都至少有一个执行线程线程在进程内部运行,本质是在进程地址空间内运行在Linux系统中,在CPU眼中,看到的PCB都要比传统的进程更轻量化透过进程虚拟地址空间,可以看到进程的大部分资源,将进程资源合理分配给每个执行流,就形成了线程执行流进程的创建伴随着进程控制块,进程地址空间以及页表的创建,虚拟地址和物理地址就是通过页表建立映射的。

m0_72940975的博客 3686

【linux线程(一)】什么是线程?怎样操作线程?

本篇文章着重讲解了线程相关的概率,以及如何在Linux下操作线程,以及一些代码的样例.最后讲解了pthread的原理,以及进程和线程的对比

杭电码农-NEO的博客 1933

【Linux系统】Linux多线程详解

由上图可以很好地理解线程为什么是CPU调度的基本单位,在CPU看来,它只关心一个独立的执行流,无论进程内部是一个还是多个执行流,CPU都是以task_struct为单位来调度的。如果计算密集型线程的数量比可用的处理器多,那么可能会有较大的性能损失,这里的性能损失指的是增加了额外的同步和调度开销,而可用的资源不变。在操作系统的的视角下,Linux下没有真正意义的线程,而是用进程模拟的线程(LWP,轻量级进程),所以Linux不会提供直接创建线程的系统调用,最多提供创建轻量级进程的接口。个字节,也就是1MB。

fufufu_的博客 6773

Linux线程(Linux和Windows的线程区别、Linux的线程函数、互斥、同步)

**线程的概念**: **线程是 CPU 调度的基本单位**。它被包含在进程之中,**是进程中的实际运作单位**。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。 **线程和进程的区别**: 1. 线程是 CPU 调度的基本单位,而进程(内核角度)是承担分配系统资源的基本实体。 2. 线程和进程最大的区别是,线程之间共用一个地址空间,而进程的地址空间彼此独立。

laimaxgg 1380

【Linux】线程控制

【Linux】线程控制:一文吃透线程控制基本用法!从接口到原理,再到模拟封装线程库接口

tan_run的博客 2275

Linux多线程——线程控制

线程是进程内的基本执行单位,作为 CPU 执行的基本单位,线程的控制与任务执行效率息息相关。合理地进行线程管理,能大大提升程序的执行效率,掌握线程的基本操作至关重要。

2401_83603768的博客 1124

Linux的线程

在一个线程中调用pthread_create()创建新的线程后,当前线程从pthread_create()返回继续往下执行,而新的线程所执行的代码由我们传给pthread_create的函数指针start_routine决定。pthread_t 类型的线程 ID :属于NPTL线程库的范畴,线程库的后续操作,就是根据该线程 ID 来操作线程的。如果计算密集型线程的数量比可用的处理器多,那么可能会有较大的性能损失,这里的性能损失指的是增加了额外的同步和调度开销,而可用的资源不变。线程需要执行的函数。

m0_46417380的博客 1586

【Linux】Linux多线程

Linux多线程线程线程的优点线程的缺点线程异常线程用途Linux进程VS线程Linux线程控制POSIX线程库创建线程线程ID及进程地址空间布局线程终止 线程 线程是进程的一个执行分支,是在进程内部(线程本质是在进程的地址空间内运行)运行的一个执行流。 Linux线程的原理:如果我们今天创建“进程”,不独立创建地址空间,用户级页表,甚至不进行IO将程序的数据和代码加载到内存,我们只创建task_struct,然后让新的PCB指向和老的PCB指向同样的mm_struct。然后,通过合理的资源分配(当前

qq_46994783的博客 5219
上一篇: 进程间的通信-IPC
下一篇: 怎么计算结构体的大小
mx_jun
博客等级 码龄5年 1605粉丝 148原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值