IO进程线程day5(2023.8.2)

news2024/11/16 15:26:16

一、Xmind整理:

父进程会拷贝文件描述符表给子进程:

 

二、课上练习:

练习1:①从终端获取一个文件的路径以及名字。②若该文件是目录文件,则将该文件下的所有文件的属性显示到终端,类似ls -l该文件夹③若该文件不是目录文件,则显示该文件的属性到终端上,类似ls -l这单个文件

include <stdio.h>
include <string.h>
include <stdlib.h>
include <head.h>
/获取文件类型
har get_fileType(mode_t m)

   switch(m&S_IFMT)
   {
   case S_IFSOCK:return('s');break;
   case S_IFLNK:return('l');break;
   case S_IFREG:return('-');break;
   case S_IFDIR:return('d');break;
   case S_IFCHR:return('c');break;
   case S_IFBLK:return('b');break;
   case S_IFIFO:return('p');break;
   }

/获取文件权限
oid get_filePermission(mode_t m)

   for(int i=0;i<9;i++)
   {
       if((m&(0400>>i))==0)
       {
           putchar('-');
           continue;
       }
       //能运行到当前位置,则代表对应位置有权限
       //需要判断是r  w  x当中的哪一个
       switch(i%3)
       {                                                                  
       case 0:putchar('r');break;
       case 1:putchar('w');break;
       case 2:putchar('x');break;
       }
   }
   return;

nt getstat(struct stat buf,char *str)

   //文件的类型和权限
   char type=get_fileType(buf.st_mode);
   printf("%c",type);
   get_fileType(buf.st_mode);
   //文件的硬链接数
   printf("%ld ", buf.st_nlink);

   //文件的所属用户
   //printf("uid: %d\n", buf.st_uid);
   //将uid转换成名字
   struct passwd* pwd = getpwuid(buf.st_uid);
   if(NULL == pwd)
   {
       ERR_MSG("getpwuid");
       return -1;
   }
   printf("%s ", pwd->pw_name);


   //文件所属组用户
   //printf("gid: %d\n", buf.st_gid);
   //将gid转换成名字
   struct group* grp = getgrgid(buf.st_gid);
   if(NULL == grp)
   {
       ERR_MSG("getgrgid");
       return -1;
   }
   printf("%s ", grp->gr_name);
   //文件大小
   printf("%ld ", buf.st_size);
   //文件的修改时间
   struct tm* info=NULL;
   info=localtime(&buf.st_mtime);
   //printf("%ld ",buf.st_ctime);
   printf("%02d %02d %02d:%02d ",info->tm_mon+1,info->tm_mday,info->tm_hou
   printf("%s\n",str);


nt main(int argc, const char *argv[])

   char str[20]="";
   char path[300]="";
   char type=0;
   struct stat buf;
   DIR* dp=NULL;
   struct dirent* rp=NULL;

   //从终端获取一个文件的路径以及名字
   printf("please enter a filename:");
   scanf("%s",str);
   getchar();

   //判断文件是否是目录文件
   if(stat(str,&buf) < 0)
   {
       ERR_MSG("stat");
       return -1;
   }
   type=get_fileType(buf.st_mode);
   if('d'==type)
   {
       //文件是一个目录文件,则需要打开目录
       dp = opendir(str);
       if(NULL == dp)
       {
           ERR_MSG("opendir");
           return -1;
       }
       printf("open success \n");

       while(1)
       {
           //循环读取目录
           rp = readdir(dp);
           if(NULL == rp)
           {
               if(0 == errno)
               {
                   printf("读取完毕\n");
                   break;
               }
               else
               {
                   ERR_MSG("readdir");
                   return -1;
               }
           }
           //将读取到的文件名传入stat获取属性
           sprintf(path,"%s%s",str,rp->d_name);
           //printf("path:%s\n",path);
           if(stat(path,&buf)<0)
           {
               ERR_MSG("stat");
               return -1;
           }
           getstat(buf,rp->d_name);
               //  printf("[%d]%s\n",++i,rp->d_name);
       }
       closedir(dp);
   }
   else
       getstat(buf,str);

   return 0;

练习2:文件IO函数实现,拷贝文件。子进程先拷贝后半部分,父进程再拷贝前半部分。允许使用sleep函数

#include <stdio.h>
#include <head.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>

int main(int argc, const char *argv[])
{
    int fd_r = open("./1.png", O_RDONLY);
    if(fd_r < 0)
    {
        ERR_MSG("open");
        return -1;
    }

    int fd_w = open("copy.png", O_WRONLY|O_CREAT|O_TRUNC, 0644);
    if(fd_w < 0)
    {
        ERR_MSG("open");
        return -1;
    }
    //计算文件大小
    off_t size = lseek(fd_r, 0, SEEK_END);

    pid_t cpid = fork();
    if(cpid > 0)
    {
        sleep(4);

        //父进程拷贝前半部分
        //将偏移量修改到0
        lseek(fd_r, 0, SEEK_SET);
        lseek(fd_w, 0, SEEK_SET);

        char c = 0;
        for(int i=0; i<size/2; i++)
        {
            read(fd_r, &c, 1);
            write(fd_w, &c, 1);
        }

        printf("前半部分拷贝完毕\n");

    }
    else if(0 == cpid)
    {                                                           
        //子进程拷贝后半部分
        //将偏移量修改到size/2
        lseek(fd_r, size/2, SEEK_SET);
        lseek(fd_w, size/2, SEEK_SET);

        char c = 0;
        for(int i=size/2; i<size; i++)
        {
            read(fd_r, &c, 1);
            write(fd_w, &c, 1);
        }                                                               

        printf("后半部分拷贝完毕\n");

    }
    else
    {
        ERR_MSG("fork");
        return -1;
    }

    close(fd_r);
    close(fd_w);

    return 0;
}
                                                                        

练习3:getpid / getppid

功能:获取进程号 、 获取父进程号

原型:

#include <sys/types.h>
#include <unistd.h>
pid_t getpid(void);
pid_t getppid(void);

返回值:

获取进程号 、 获取父进程号

练习4:_exit

功能:结束进程,销毁其在内存中的资源,且直接摧毁缓冲区,不会刷新缓冲区!!!

原型:

#include <unistd.h>
void _exit(int status);

参数:

int status:可以传递进程退出状态值给其父进程,父进程可以通过wait/ waitpid函数接收。可以传递任意整型;

练习5:exit

功能:结束进程,销毁其在内存中的资源,会刷新缓冲区!!!

原型:

#include <stdlib.h>
void exit(int status);

参数:

int status:可以传递进程退出状态值给其父进程,父进程可以通过wait/ waitpid函数接收。可以传递任意整型;

小练1:

小练2:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <head.h>
int main(int argc, const char *argv[])
{
    pid_t cpid = fork();
    if(cpid > 0) //父进程
    {
        printf("parent\n");
        //阻塞函数,阻塞等待任意子进程退出
        pid_t wpid = wait(NULL);
        printf("wpid =%d\n",wpid);

        while(1)
        {                                                                         
            printf("this is parent: %d %d\n",getpid(),cpid);
            sleep(1);
        }
    }
    else if(0 == cpid)
    {
        int i = 0;
        while(i < 3)
        {
            printf("this id child: %d %d\n",getppid(),getpid());
            sleep(1);
            i++;
        }
        printf("子进程准备退出\n");
        //_exit(0);    //退出进程,不会刷新缓冲区
        exit(0);    //退出进程,会刷新缓冲区

        printf("子进程已经退出\n");
    }
    else
    {
        perror("fork");
        return -1;
    }

    return 0;
}

练习6:wait

功能:1.阻塞函数,阻塞等待任意子进程退出

           2.回收退出的子进程的资源,(回收僵尸进程)

           3.接收子进程退出状态

原型:

#include <sys/types.h>
#include <sys/wait.h>
pid_t wait(int *wstatus);

参数:

 int *wstatus:接收子进程传递回来的退出状态值,若不想接收,则填NULL;

返回值:

>0, 成功返回退出的子进程的PID号;
=-1,函数运行失败,更新errno; 
若没有子进程,则wait函数运行失败;
父进程只能回收子进程,无法回收孙子进程。

 注:①若子进程退出,父进程没有回收子进程的资源,此时子进程会变成僵尸进程。

        ②没有子进程,则wait函数运行失败

练习7:子进程退出状态

        wait(int* wstatus)中,int* wstatus指向的int类型参数,只有[8bit, 15bit]用于存储子进程传递的退出状态值。范围为[0, 255]。

所以子进程只能传递256种状态

1)从wstatus中提取子进程退出状态值 

int wstatus = -1;
pid_t wpid = wait(&wstatus);    
printf("wpid = %d  wstatus=%d\n", wpid, wstatus>>8); 
WEXITSTATUS(wstatus): 提取wstauts中子进程传递的退出状态;--> ((status) & 0xff00) >> 8)

2)判断子进程是否正常退出 

WIFEXITED(wstatus)     若正常退出,则返回真。
正常退出: exit  _exit  主函数调用return退出。

小练: 

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <head.h>
int main(int argc, const char *argv[])
{
    pid_t cpid = fork();
    if(cpid > 0) //父进程
    {
        printf("parent\n");
        //阻塞函数,阻塞等待任意子进程退出
        int wstatus = -1;
        pid_t wpid = wait(&wstatus);
        printf("wpid = %d wstatus= %d\n",wpid,WEXITSTATUS(wstatus));

        if(WIFEXITED(wstatus))
            printf("子进程正常退出\n");
        else
            printf("子进程异常退出\n");

        while(1)
        {
            printf("this is parent: %d %d\n",getpid(),cpid);
            sleep(1);
        }
    }
    else if(0 == cpid)
    {
        int i = 0;
        while(i < 3)
        {
            printf("this is child: %d %d\n",getppid(),getpid());
            sleep(1);
        //  i++;
        }
        printf("子进程准备退出\n");
        //_exit(0);    //退出进程,不会刷新缓冲区
        exit(0);    //退出进程,会刷新缓冲区

        printf("子进程已经退出\n");
    }                                                                    
    else
    {
        perror("fork");
        return -1;
    }

    return 0;
}

 

练习8:waitpid

功能:阻塞等待指定子进程退出

原型:

 #include <sys/types.h>
 #include <sys/wait.h>
 pid_t waitpid(pid_t pid, int *wstatus, int options);

参数:

 pid_t pid:
            < -1  阻塞等待指定进程组下的任意一个子进程退出;

            -1    阻塞等待当前进程下的任意一个子进程退出; 与wait函数的功能基本一致;

            0     阻塞等待当前进程组下的任意一个子进程退出;

            > 0   阻塞等待指定的子进程退出;子进程的pid号 == pid参数;
        
    int *wstatus:接收子进程传递回来的退出状态值,若不想接收,则填NULL;
    int options:    
        
        0:阻塞方式运行,当指定的子进程没有退出的时候,该函数阻塞,直到指定子进程退出,解除阻塞;
        WNOHANG:非阻塞方式运行,当指定的子进程没有退出,该函数不阻塞,立即返回; 

返回值:

 成功,>0, 成功回收到的子进程的pid号;
       =0, 函数运行成功,但是此时子进程没有退出。
         
    函数运行失败,返回-1,更新errno;        
    
1. 若指定的子进程不存在(没有子进程)的时候,函数运行失败;   
2. 子进程无法回收父进程的资源,        
3. 同级之间无法相互回收资源。

小练: 

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <head.h>
int main(int argc, const char *argv[])
{
    pid_t cpid = fork();
    if(cpid > 0) //父进程
    {
        printf("parent\n");
        //阻塞函数,阻塞等待任意子进程退出,并回收子进程的资源
        //pid_t wpid = waitpid(-1,NULL,0);

        //非阻塞方式运行,若运行到waitpid的时候,子进程没有退出,则返回0
        //若运行到waitpid的时候,子进程已经退出了,则收回尸体,并返回子进程的pid号
        sleep(4);
        pid_t wpid = waitpid(-1,NULL,WNOHANG);
        printf("wpid = %d\n",wpid);

        while(1)
        {
            printf("this is parent: %d %d\n",getpid(),cpid);
            sleep(1);
        }
    }
    else if(0 == cpid)
    {
        int i = 0;
        while(i < 3)
        {
            printf("this is child: %d %d\n",getppid(),getpid());
            sleep(1);
            i++;
        }                                                                                
        printf("子进程准备退出\n");
        //_exit(0);    //退出进程,不会刷新缓冲区
        exit(0);    //退出进程,会刷新缓冲区

        printf("子进程已经退出\n");
    }
    else
    {
        perror("fork");
        return -1;
    }

    return 0;
}

练习9:孤儿进程

父进程退出,子进程不退出,此时子进程被1号(init)进程收养,变成孤儿进程。

孤儿进程会脱离终端控制,且运行在后端,不能用ctrl+c杀死后端进程,但是可以被kill -9杀死。

 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
 #include <head.h>
 int main(int argc, const char *argv[])
 {
     //父进程退出,子进程不退出
     pid_t cpid = fork();
     if(cpid > 0) //父进程
     {
     }
     else if(0 == cpid)
     {
         while(1)
         {
             printf("this is child: %d %d\n",getppid(),getpid());
             sleep(1);
         }
     }
     else
     {
         perror("fork");
         return -1;
     }
 
     return 0;
 }
 

练习10:僵尸进程

子进程退出,父进程不退出去,且父进程没有给子进程收尸,此时子进程就变成僵尸进程。

注意:

  • 僵尸进程只能被回收,不能被杀死。
  • 僵尸进程有危害:占用进程号,占用部分内存空间,占用物理空间,占用进程调度块(PCB)等等...
  • 回收僵尸进程的方式:
    1. 结合信号的方式回收僵尸进程:当子进程退出后,通知父进程收尸。
    2. wait / waitpid函数回收。缺点:阻塞函数,父进程无法做自己的事情。非阻塞形式,有可能收不到。
    3. 退出父进程后,子进程的资源由内核自动回收。
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
 #include <head.h>
 int main(int argc, const char *argv[])
 {
     //子进程退出,父进程不退出
     pid_t cpid = fork();
     if(cpid > 0) //父进程
     {
         while(1)
         {
             printf("this is parent: %d %d\n",getpid(),cpid);
             sleep(1);
         }
     }
     else if(0 == cpid)
     {
     }
     else
     {
         perror("fork");
         return -1;
     }
 
     return 0;
 }

练习11:守护进程(幽灵进程)

1.守护进程脱离于终端,且运行在后端

2.守护进程在执行过程中不会将信息显示在任何终端上,避免影响前端任务执行。且不会被任何终端产生的终端信息所打断。

3.守护进程目的:需要周期性执行某个任务或者周期性等待处理某些事情的时候,为了避免影响前端执行或者被前端信息打断的时候,可以使用守护进程。

守护进程的创建:

1.创建孤儿进程:所有工作都在子进程中执行,从形式上脱离终端控制。

   fork(), 退出父进程

2.创建新的会话组:使子进程完全独立出来,防止兄弟进程对其有影响

setsid() 函数
功能:创建一个新的进程组和会话组,成为该进程组和会话组组长
原型:
       #include <sys/types.h>
       #include <unistd.h>
       pid_t setsid(void);

3.修改当前孤儿进程的运行目录为不可卸载的文件系统:例如根目录,/tmp

   防止运行目录被删除后,导致进程崩溃

chdir函数
功能:修改运行目录;
原型:
      #include <unistd.h>

       int chdir(const char *path);
chdir("/");

注意:从当前位置往后,运行在指定的目录下

4.重设文件权限掩码:umask(0), 一般清零;

5.关闭所有文件描述符,从父进程继承过来的文件描述符不会用到,浪费资源。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <head.h>
int main(int argc, const char *argv[])
{
    //创建孤儿进程
    pid_t cpid = fork();
    if(0 == cpid)
    {
        //创建新的会话
        pid_t sid = setsid();
        printf("sid = %d\n", sid);

        //修改运行目录为不可卸载的文件目录下
        chdir("/");

        //清空文件权限掩码
        umask(0);

        //关闭所有文件描述符
        for(int i = 0; i<getdtablesize(); i++)     
            close(i);

        while(1)
        {                                          
            //守护进程运行的周期性代码
            sleep(1);
        }
    }
    return 0;
}

三、课后作业:

1.打印时钟在终端上,若终端输入quit,结束时钟

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <head.h>
int main(int argc, const char *argv[])
{
    pid_t cpid = fork();
    if(cpid > 0)
    {
        time_t t;
        struct tm *info=NULL;
        while(1)
        {
            if(waitpid(-1,NULL,WNOHANG) > 0)
                break;
            t = time(NULL);
            info = localtime(&t);
            printf("%d-%02d-%02d %02d:%02d:%02d\r",\
                    info->tm_year+1900,info->tm_mon+1,\
                    info->tm_mday,info->tm_hour,info->tm_min,info->tm_sec);
            fflush(stdout);
            sleep(1);
        }
    }
    else if(0 == cpid)
    {
        char str[10]="";
        while(1)
        {                                                                   
            scanf("%s",str);
            if(0 ==strcmp(str,"quit"))
                exit(0);
            sleep(1);
        }
    }
    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/827472.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

异常和中断的区别

异常和中断的区别 中断异常中断和异常的相同点中断和异常的区别 中断 中断是由硬件设备产生的&#xff0c;而它们从物理上说就是电信号&#xff0c;之后&#xff0c;它们通过中断控制器发送给CPU&#xff0c;接着CPU判断收到的中断来自于哪个硬件设备&#xff08;这定义在内核…

手机屏幕视窗机器视觉定位软硬件-康耐德

【检测目的】 手机屏幕视窗视觉定位 【效果图片】 【安装示意图】 【硬件配置】

vs20222使用qt做材料库

Material.h #pragma once #include "QtWindow.h" #include "ui_Widget.h" #include <QWidget> #include <QObject> #include <QDialog>//防止中文乱码 #if _MSC_VER >= 1600 #pragma execution_character_set("utf-8")// …

【vue】vue 里面使用 v-html 插入的文本带有换行符‘\n‘不换行

最近开发vue2 项目 &#xff0c;接口返回的是类似于这样的数据&#xff1a;我是第一行的哦\n我是第二行的哦 我是直接这样渲染的&#xff0c; //html <p v-htmltext></p>//渲染值 this.text "我是第一行的哦\n我是第二行的哦"但结果却是不如意&#x…

数据之海 — 探索大数据的无尽可能

数据之海 — 探索大数据的无尽可能 &#x1f498; &#x1f498;1. 什么是大数据&#xff1f;&#x1f498; &#x1f498;2. 大数据的应用领域&#x1f496; &#x1f496;2.1 商业决策&#x1f496; &#x1f496;2.2 医疗保健&#x1f496; &#x1f496;2.3 城市规划&#…

【机器学习】处理样本不平衡的问题

文章目录 样本不均衡的概念及影响样本不均衡的解决方法样本层面欠采样 &#xff08;undersampling&#xff09;过采样数据增强 损失函数层面模型层面采样集成学习 决策及评估指标 样本不均衡的概念及影响 机器学习中&#xff0c;样本不均衡问题经常遇到&#xff0c;比如在金融…

安全文件传输:如何避免数据泄露和黑客攻击

网络安全问题日益严重&#xff0c;导致许多数据被泄露和黑客袭击的事件频发。为了保证文件传输的安全&#xff0c;需要实施一系列安全文件传输策略来防止数据被泄露和黑客袭击。 第一、选择适合的加密方法是非常关键的 加密是一种将明文转换成密文的过程&#xff0c;这样只有授…

再探python装饰器

参考视频教学&#xff1a; 可能是b站上最好的Python装饰器教程_哔哩哔哩_bilibili 【python】如何在class内部定义一个装饰器&#xff1f;这里的坑你要么不知道&#xff0c;要么不会填&#xff01;_哔哩哔哩_bilibili 推荐&#xff01;先学习第一个视频&#xff0c;再学习第…

Selenium 根据元素文本内容定位

使用xpath定位元素时&#xff0c;有时候担心元素位置会变&#xff0c;可以考虑使用文本内容来定位的方式。 例如图中的【评价】按钮&#xff0c;只有按钮文本没变&#xff0c;就可以定位到该元素。 xpath内容样例&#xff1a; # 文本内容完全匹配 //button[text()"评价&…

赋能教育数字化转型,经管大数据课程教学训练营线下培训圆满收官!

全面推进教学教改、加快学科专业交叉融合&#xff0c;2023年7月30日&#xff0c;由邮电出版有限责任公司联合上海和今信息科技有限公司&#xff08;下简称“和鲸科技”&#xff09;、山东省中国石油大学&#xff08;华东&#xff09;大数据人才培训示范基地主办的“数字化转型背…

【三等奖方案】Web攻击检测与分类识别赛题「Cyan」团队解题思路

2022 CCF BDCI 数字安全公开赛「Web攻击检测与分类识别」赛题Cyan战队获奖方案 地址&#xff1a;http://go.datafountain.cn/4Zj 团队简介 团队成员来自中国科学院大学&#xff0c;对数据挖掘与网络安全有浓厚兴趣&#xff0c;曾多次获得大数据安全分析等比赛的Top名次。希望…

网络:SecureCRT介绍

1. 使用Tab键补全时出现^I&#xff0c;如下操作

MySQL数据库服务器的简化(此操作针对开发人员,不推荐运维人员)

目录 引言 一&#xff0c;5.7之前版本简化 二&#xff0c;5.7之后版本简化 引言 简化数据库只是为了让数据库文件更小更简单。对于开发人员来说是一个不错的选择&#xff0c;h是将数据库只用于简单的数据操作&#xff0c;但是对于运维人员来说就是灾难。 建议每次删除前可以备…

vscode 通过mongoose 连接mongodb atlas

了解mongodb 的项目结构 1.代表集群名称 > 2.代表数据库名称>3.代表每个 collection名称 三者范围为从大到小的关系 &#xff08;一对多&#xff09;。每个集群有不同的连接地址、用户信息&#xff08;Database Access&#xff09;、ip配置信息&#xff08;Network Acce…

安全狗V3.512048版本绕过

安全狗安装 安全狗详细安装、遇见无此服务器解决、在windows中命令提示符中进入查看指定文件夹手动启动Apache_安全狗只支持 glibc_2.14 但是服务器是2.17_黑色地带(崛起)的博客-CSDN博客 安全狗 safedogwzApacheV3.5.exe 右键电脑右下角安全狗图标-->选择插件-->安装…

Vue3基础(1)

1.简单的vue实例 1.data函数介绍 也可以修改data里的数据 2.自定义函数 调用函数 3.Vue模板语法 &#xff08;1).V-html (2)三目运算符的支持 &#xff08;3&#xff09;对函数的支持 &#xff08;4&#xff09;v-bind 值动态修改 4.指令 1.v-if和v-else的使用

数据截断、频谱泄漏与窗函数的选择

目录 数据截断、频谱泄漏与窗函数的选择 什么是频谱泄漏&#xff1f; 解决频谱泄漏问题的方法 主瓣和旁瓣 窗函数介绍 窗函数解决频谱泄漏问题的原理 窗函数的种类、特点和如何使用 1、矩形窗 2、三角窗 3、汉宁窗 4、海明窗 5、布莱克曼窗 6、巴特窗&#xff1a;…

docker 保存和载入镜像

查看本机docker镜像 docker images保存镜像 docker save -o /home/space/work1/docker_qnx7.1.tar.gz a01ee6d74c36复制镜像到其他服务器 scp /home/space/work1/docker_qnx7.1.tar.gz XXXIP:/home/dell/work1/登录新 服务器操作 docker load -i docker_qnx7.1.tar.gz载入后…

滇医通微信小程序分析笔记

注意 本文章仅供学习交流使用&#xff0c;如果你是铁粉你就会知道博主之前发布过一篇相关的文章&#xff0c;但是由于代码涉及到法律相关所以就隐藏了&#xff0c;两年的时间过去了&#xff0c;因为女朋友已经早早安排上了&#xff0c;所以就搁置了&#xff0c;本次不做代码分…

【Linux】Linux服务器连接百度网盘:实现上传下载

【Linux】Linux服务器连接百度网盘&#xff1a;实现上传下载 文章目录 【Linux】Linux服务器连接百度网盘&#xff1a;实现上传下载1. 前言2. 具体过程2.1 pip 安装所需包2.2 认证&#xff08;第一次连接需要认证&#xff09;2.3 下载所需文件或者目录2.4 其他指令使用2.5 注意…