Linux高级编程——进程

1.进程的含义?

进程是一个程序执行的过程,会去分配内存资源,cpu的调度

PID, 进程标识符
当前工作路径   chdir
umask  0002
进程打开的文件列表  文件IO中有提到 (类似于标准输入 标准输出的编号,系统给0,1,2

                                                                标准输入 标准输出 标准错误)
信号相关设置 处理异步io,

用户id,组id


进程资源的上限的命令:ulimit -a,显示资源上限。

2.进程和程序的区别?
(1)程序:静态
存储在硬盘中代码,数据的集合
(2)进程:动态
程序执行的过程,包括进程的创建、调度、消亡
.c ----> a.out-----> process(pid)
1)程序是永存,进程是暂时
2)进程有程序状态的变化,程序没有
3)进程可以并发,程序无并发
4)进程与进程会存在竞争计算机的资源
5)一个程序可以运行多次,变成多个进程
一个进程可以运行一个或多个程序
内存的分布
0-3G,是进程的空间,3G-4G是内核的空间,虚拟地址
虚拟地址 *  物理内存和虚拟内存的地址 映射表 1page=4k    mmu

这部分占3G,其他部分是操作系统

进程分类:
1、交互式进程
2、批处理进程   shell脚本 
3、 守护进程 


3.进程的作用? 并发,并行区别。
while (1) { while (1) { 上下左右
发视频
} }

同一时刻完成多个任务
4.进程的状态:
3个状态,就绪→执行态→阻塞(等待,睡眠)基本操作系统

linux中的状态,运行态,睡眠态,僵尸,暂停态。

5.进程的调度,进程上下文切换
内核主要功能之一就是完成进程调度, 硬件,bios,io,文件系统,驱动
调度算法, other,idle
             rr,fifo
宏观并行
微观串行

6.查询进程相关命令
 

1.ps aux

查看进程相关信息

1.就绪态、运行态 R
2.睡眠态、等待态
可唤醒等待态 S
不可唤醒等待态 D
3.停止态 T
4.僵尸态 Z
5.结束态

2.top
根据CPU占用率查看进程相关信息

3.kill和killall发送一个信号
kill -2 PID  15
发送信号+PID对应的进程,默认接收者关闭

killall -9 进程名
发送信号 进程名对应的所有进程
killall a.out

原语:
1.fork();
pid_t fork(); 叉子
一次调用,会返回两次。
子进程先进行和是父进程先进程,顺序不确定。

父与子 的 变量不共享。


子进程复制父进程的0到3g空间和父进程内核中的PCB但id号不同

但子的id号不是0,

功能:通过该函数可以从当前进程中克隆一个同名新进程。
  克隆的进程称为子进程,原有的进程称为 父进程。
  子进程是父进程的完全拷贝。
  子进程的执行过程是从fork函数之后执行。
  
  子进程与父进程具有相同的代码逻辑。

返回值:int 类型的数字。
在父进程中:成功 返回值是子进程的pid号 >0
失败 返回-1;
在子进程中:成功 返回r'r'r'r'r'r'r'r'r'r'r'r'r值 0
失败 无


面试题:
一次fork生成几个进程?他们之间的关系是什么样的?
如果两次fork同时前后执行,会生成几个进程?他们之间的
关系如何表示,有多少个子进程,有没有孙进程?
2.getpid
pid_t getpid(void);
功能:
获得调用该函数进程的pid
参数:
缺省
返回值:
进程的pid
       
  
pid_t getppid(void);
功能:
获得调用该函数进程的父进程pid号
参数:
缺省
返回值:
返回父进程id号

fork()&&fork()||fork();


while(1)sleep(1);
应用场合
1)一个进程希望复制自己,使父子进程同时执行同的代码段。网络服务中会比较多见。
2)一个进程需要执行一个不同的程序。fork+exec

7、父子进程的关系:
子进程是父进程的副本。子进程获得父进程数据段,堆,栈,正文段共享。
在fork之后,一般情况那个会先运行,是不确定的。如果非要确定那个要先运行,需要IPC机制。

区别:
1)fork的返回值
2)pid不同(一般来说子的要比父的大)


8、进程的终止:8种情况
正常结束:

1)main 中return
2)exit(), c库函数,会执行io库的清理工作,关闭所有 的流,以及所有打开的文件。已经清理数(atexit) 。
3)_exit,_Exit 会关闭所有的已经打开的文件,不执行清理函数。
4) 主线程退出
5)主线程调用pthread_exit
异常终止
6)abort()  在非常紧急的情况内核调用函数来退出进程
7)signal   kill pid
8)最后一个线程被pthread_cancle
 

9.僵尸进程和孤儿进程

危害

孤儿进程(Orphan Process)

定义

产生原因

特点

  • 僵尸进程(Zombie Process)

    定义

  • 僵尸进程是指一个已经终止、但是其父进程尚未对其进行善后处理的(获取终止进程的有关信息,释放它仍占用的资源)的进程。
  • 产生原因

  • 当子进程比父进程先结束,而父进程没有回收子进程,释放子进程占用的资源时,子进程将成为一个僵尸进程。
  • 特点

  • 僵尸进程不占用除进程表项外的任何系统资源。
  • 僵尸进程不能被kill命令杀死,因为它已经不存在于活动进程列表中。
  • 如果父进程不调用wait或waitpid等函数来回收僵尸进程,那么保留的那段信息就不会释放,其进程号就会一直被占用。
  • 系统所能使用的进程号是有限的,如果大量的产生僵尸进程,将因为没有可用的进程号而导致系统不能产生新的进程。
  • 孤儿进程是指在其父进程执行完成或被终止后仍继续运行的一类进程。
  • 当一个父进程由于正常完成工作而退出或由于其他情况被终止,而它的一个或多个子进程却还在运行时,这些子进程将成为孤儿进程。
  • 孤儿进程会被init进程(进程号为1)所收养,并由init进程对它们完成状态收集工作。
  • 孤儿进程本身并没有危害,因为它们的资源回收工作由init进程负责。

1)exit     库函数
退出状态,终止的进程会通知父进程,自己使如何终止的。如果是正常结束(终止),则由exit传入的参数。如果是异常终止,则有内核通知异常终止原因的状态。任何情况下,负进程都能使用wait,waitpid获得这个状态,以及资源的回收。

缓冲区里的数据还会被保留
void exit(int status) 
exit(1);
功能:
让进程退出,并刷新缓存区
参数:
status:进程退出的状态
返回值:
缺省

EXIT_SUCCESS 0
EXIT_FAILURE 1

return  当该关键字出现在main函数中时候可以结束进程
如果在其他函数中则表示结束该函数。
exit -> 刷新缓存区 -> atexit注册的退出函数 -> _exit】

2)._exit    系统调用
void _exit(int status);
功能:
让进程退出,不刷新缓存区
参数:
status:进程退出状态
返回值:
缺省

缓冲区的数据不会被保留


 mian(int agc,argv)
{
main();
}  

//缓冲区//

行缓冲

全缓冲(文件)

缓冲区大小为4k

出缓冲区的条件少了一个“\n”.

回调函数:调用下面的函数时,在()里填入函数,这个函数是进程退出前执行的函数
3.atexit
int atexit(void (*function)(void));

函数类型不能变化

功能:
注册进程退出执行的函数(资源回收,清理函数)
参数:
function:函数指针
指向void返回值void参数的函数指针
返回值:
成功返回0
失败返回非0

当程序调用exit或者由main函数执行return时,所有用atexit
注册的退出函数,将会由注册时顺序倒序被调用

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
char * tmp=NULL;
void clean(void)
{
    printf("this is clean %s\n",tmp);
    free(tmp);
}
int main(int argc, char *argv[])
{
    atexit(clean);
    tmp =(char*) malloc(50);
    strcpy(tmp,"hello");

    printf("123123\n");


    return 0;
}

4、进程空间的回收

exit(20); ()里的数字填入哪个都可以只要不超过127

wait/waitpid

pid_t wait(int *status);
功能:该函数可以阻塞等待任意子进程退出
      并回收该进程的状态。
       一般用于父进程回收子进程状态。

参数:status 进程退出时候的状态
  

返回值:成功 回收的子进程pid
失败 -1;

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(int argc, char *argv[])
{
    pid_t pid = fork();
    if(pid>0)
    {

        printf("father pid:%d ppid:%d\n",getpid(),getppid());
        pid_t recycle_pid = wait(NULL);
        printf("recycle pid %d\n",recycle_pid);
        sleep(10);
        printf("aaa\n");

    }
    else if(0 == pid)
    {
        sleep(3);    
        printf("child pid:%d ppid:%d\n",getpid(),getppid());
        exit(0);
    }
    else 
    {
        perror("fork");
        return 1;
    }
    
    return 0;
}

用以下宏来判断status进程退出时的状态:

如果不关心其退出状态一般用NULL表示
  如果要回收进程退出状态,则用WEXITSTATUS回收。

WIFEXITED(status)  是不是正常结束 

WEXITSTATUS(status) 使用这个宏去那返回值

WIFSIGNALED(status) 是不是收到了信号而终止的   

WTERMSIG(status)如果是信号终止的,那么是几号信号。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(int argc, char *argv[])
{
    pid_t pid = fork();
    if(pid>0)
    {
        //stat("1.txt",&st);
        int status;
        printf("father pid:%d ppid:%d\n",getpid(),getppid());
        pid_t recycle_pid = wait(&status);
        if(WIFEXITED(status))
        {
            
        printf("child normal terminal,recycle pid %d , exit value %d\n"
               ,recycle_pid,WEXITSTATUS(status));
        }
        if(WIFSIGNALED(status))
        {
            printf("child terminal bu signal ,rrecycle pid %d, signal num %d \n"
                   ,recycle_pid,WTERMSIG(status));
        }

    }
    else if(0 == pid)
    {
        printf("child pid:%d ppid:%d\n",getpid(),getppid());
        sleep(5);    
        exit(20);
    }
    else 
    {
        perror("fork");
        return 1;
    }
    
    return 0;
}

pid_t wait(int *status);

    1)如果所有的子进程都在运行,在阻塞
    2)如果一个子进程终止,正在等待的父进程则获得终止状态,获得子进程的状态后,立刻返回。
    3)如果没有子进程,则立即出错退出。

    waitpid(-1,status,0)=wait(status);
    pid_t waitpid(pid_t pid, int *status, int options);
    < -1 回收指定进程组内的任意子进程
    -1 回收任意子进程,组内外
    0 回收和当前调用waitpid一个组的所有子进程,组内
    > 0 回收指定ID的子进程
     waitpid (-1,a,0)  == wait(a);
     status 子进程退出时候的状态,
              如果不关注退出状态用NULL;
      options 选项:
                  0  表示回收过程会阻塞等待
                WNOHANG 表示非阻塞模式回收资源。
    返回值:成功 返回接收资源的子进程pid
        失败  -1
        0,
        
        EAGAIN

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(int argc, char *argv[])
{
    pid_t pid = fork();
    if(pid>0)
    {
        //stat("1.txt",&st);
        int status;
        printf("father pid:%d ppid:%d\n",getpid(),getppid());
        while(1)
        {
            pid_t recycle_pid = waitpid(pid,&status,WNOHANG );
            if(recycle_pid == pid)
            {
                if(WIFEXITED(status))
                {

                    printf("child normal terminal,recycle pid %d , exit value %d\n"
                           ,recycle_pid,WEXITSTATUS(status));
                }
                if(WIFSIGNALED(status))
                {
                    printf("child terminal bu signal ,rrecycle pid %d, signal num %d \n"
                           ,recycle_pid,WTERMSIG(status));
                }
                
                break;
            }
            else 
            {
                printf("子进程未结束,稍后在试\n");
            }
        }

    }
    else if(0 == pid)
    {
        printf("child pid:%d ppid:%d\n",getpid(),getppid());
        sleep(5);    
        exit(20);
    }
    else 
    {
        perror("fork");
        return 1;
    }
    
    return 0;
}

练习:
    设计一个多进程程序,用waitpid函数指定回收
    其中的某个进程资源并将其状态打印输出。
    其他的进程都以非阻塞方式进行资源回收。
    

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(int argc, char *argv[])
{
    int i = 0;
    pid_t pid[5]={0};
    for(i=0;i<5;i++)
    {
        pid[i] = fork();
        if(pid[i]>0)
        {
            continue;
        }
        else if(0 == pid[i])
        {
            printf("child pid:%d ppid:%d\n",getpid(),getppid());
            sleep(rand()%5+1);    
            exit(0);
        }
        else 
        {
            perror("fork");
            return 1;
        }

    }

    int status;
    while(1)
    {
        pid_t recycle_pid = waitpid(pid[2],&status,WNOHANG );
        if(recycle_pid == pid[2])
        {
            if(WIFEXITED(status))
            {

                printf("child normal terminal,recycle pid %d , exit value %d\n"
                       ,recycle_pid,WEXITSTATUS(status));
            }
            if(WIFSIGNALED(status))
            {
                printf("child terminal bu signal ,rrecycle pid %d, signal num %d \n"
                       ,recycle_pid,WTERMSIG(status));
            }

            break;
        }
        else 
        {
           // printf("子进程未结束,稍后在试\n");
        }
    }
    return 0;
}

10.execute
exec族
用fork创建子进程后执行的是和父进程相同的程序(但有可能执行不同的代码分支),
子进程往往要调用一种exec函数以执行另一个程序。当进程调用一种exec函数时,该进程的
用户空间代码和数据完全被新程序替换,从新程序的启动例程开始执行。执行完毕不回原程序调用exec并不创建
新进程,所以调用exec前后该进程的id并未改变。
其实有六种以exec开头的函数,统称exec函数:
vector
ls -l -i list 
execl("/bin/ls","-l","-i",NULL);
execlp("ls","-l","-i",NULL);
#include <unistd.h>
int execl(const char *path, const char *arg, ...);
int execv(const char *path, char *const argv[]);

key=value
int execle(const char *path, const char *arg, ..., char *const envp[]);
int execle(const char *path, const char *arg, ..., char *const envp[]);

int execve(const char*path,char*const argv[],char*const evnp[]);
int execlp(const char *file, const char *arg, ...);
echo $PATH
PATH= 
int execvp(const char *file, char *const argv[]);


int execve(const char *path, char *const argv[], char *const envp[]);

这些函数的区别
    1),前4个使用路径名作为参数,后面两个使用文件名做参数
    当filename中,含有/时视为路径名,否则就按PATH变量,在指定目录下查找可执行文件。
    2)相关的参数表传递
    l表示list,v表示vector
    execl,execlp,execle,需要将参数一个一个列出,并以NULL结尾。
    execv,execvp,execve,需要构造一个参数指针数组,然后将数组的地址传入。

    3)以e结尾的函数,可以传入一个指向环境字符串的指针数组的指针。其他未指定环境变量,使用父进程继承过来的。(一般不调用带环境变量的,不主动改变环境变量)
execve 是真正的系统调用
这些函数如果调用成功则加载新的程序从启动代码开始执行,不再返回,如果调用出错
则返回-1,所以exec函数只有出错的返回值而没有成功的返回值。

char *const ps_argv[] ={"ps", "-o", "pid,ppid,pgrp,session,tpgid,comm", NULL};
char *const ps_envp[] ={"PATH=/bin:/usr/bin", "TERM=console", NULL};
execl("/bin/ps", "ps", "-o", "pid,ppid,pgrp,session,tpgid,comm", NULL);
execv("/bin/ps", ps_argv);
execle("/bin/ps", "ps", "-o", "pid,ppid,pgrp,session,tpgid,comm", NULL, ps_envp);
execve("/bin/ps", ps_argv, ps_envp);
execlp("ps", "ps", "-o", "pid,ppid,pgrp,session,tpgid,comm", NULL);

execvp("ps", ps_argv);

#include <stdio.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
    // firefox www.taobao.com 
    execl("/usr/bin/firefox","firefox","www.taobao.com",NULL);
    printf("看见就错了\n");
    return 0;
}
#include<stdio.h>
#include<unistd.h>
int main(int argc, const char *argv[])
{
	//execl("/bin/ls","ls","-a","-l","-h","-F","--color",NULL);
	//p:系统中的环境路径env path能找到
	execlp("ls","ls","-a","-l","-h","-F","--color",NULL);

	return 0;
}
#include <stdio.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
    
    char*const arg[]={"ls","-a","-l","-h","-F","--color",NULL};
    execv("/bin/ls",arg);
    printf("看见就错了\n");
    return 0;
}
#include <stdio.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
   
    char*const arg[]={"ls","-a","-l","-h","-F","--color",NULL};
 
    execvp(arg[0],arg);
    printf("看见就错了\n");
    return 0;
}

在一个程序main中调用文件中另一个程序  1.c


#include <stdio.h>
int main(int argc, char *argv[])
{
    printf("argc is %d\n",argc);
    int i = 0 ;
    for(i=0;i<argc;i++)
    {
        printf("%d %s\n",i,argv[i]);
    }
    return 0;
}
#include<stdio.h>
#include<unistd.h>
int main(int argc, const char *argv[])
{
	execl ("/home/linux/cpz/process/cpz","./cpz","1","2","3","4",NULL);

	return 0;
}


 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

点云处理实战 点云平面拟合

目录 一、什么是平拟合 二、拟合步骤 三、数学原理 1、平面拟合 2、PCA过程 四、代码 一、什么是平拟合 平面拟合是指在三维空间中找到一个平面,使其尽可能接近给定的点云。最小二乘法是一种常用的拟合方法,通过最小化误差平方和来找到最优的拟合平面。 二、拟合步骤…

1.1章节print输出函数语法八种 使用和示例

1.打印变量和字符串 2-4.三种使用字符串格式化 5.输出ASCLL码的值和中文字符 6.打印到文件或其他对象&#xff08;而不是控制台&#xff09; 7.自定义分隔符、和换行符和结束符 8.连接符加号连接字符串 在Python中&#xff0c;print() 函数用于在控制台上输出信息。这是一个非常…

设置日历程序

目录 一 设计原型 二 后台源码 一 设计原型 二 后台源码 namespace 设置日历 {public partial class Form1 : Form{public Form1(){InitializeComponent();}private void dateTimePicker1_ValueChanged(object sender, EventArgs e){richTextBox1.Text dateTimePicker1.T…

React@16.x(42)路由v5.x(7)常见应用场景(4)- 路由切换动画

目录 1&#xff0c;实现路由切换基础样式 2&#xff0c;使用 CSSTransition 添加动画1&#xff0c;自定义动画组件 *TransitionRoute.jsx*2&#xff0c;*App.jsx*3&#xff0c;样式改动 3&#xff0c;注意点 通过一个例子来说明如何实现。 1&#xff0c;实现路由切换 基础样式…

prompt:我是晚餐盲盒,只要你问出“今晚吃什么”我就将为你生成美妙的食物推荐。

使用方法&#xff1a;在ChatGP粘贴下面提示词模型&#xff0c;点击输出。然后再问“晚餐有什么好吃的&#xff1f;”&#xff0c;AI输出丰种食物供你选择。抽到什么吃什么&#xff0c;极大的解决选择困难的问题。 客户需要生成1000条俏皮灵动&#xff0c;趣味盎然&#xff0c;比…

搭建 MySQL MHA

搭建 MySQL MHA 搭建 MySQL MHA实验拓扑图实验环境实验思路MHA架构故障模拟 实验部署数据库安装主从复制部署时间同步主服务器配置从服务器配置创建链接 MHA搭建安装依赖的环境安装 node 组件安装 manager 组件配置无密码认证在 manager 节点上配置 MHA管理 mysql 节点服务器创…

UI(二)控件

文章目录 PatternLockProgressQRCodeRadioRatingRichTextScollBarSearchSelectSlideSpanStepper和StepperItemTextTextAreaTextClockTextInputTextPickerTextTimerTimePickerToggleWeb PatternLock PatternLock是图案密码锁组件&#xff0c;以九宫格图案的方式输入密码&#x…

RTDETR更换优化器——Lion

RTDETR更换Lion优化器 论文&#xff1a;https://arxiv.org/abs/2302.06675 代码&#xff1a;https://github.com/google/automl/blob/master/lion/lion_pytorch.py 简介&#xff1a; Lion优化器是一种基于梯度的优化算法&#xff0c;旨在提高梯度下降法在深度学习中的优化效果…

vue3中通过vditor插件实现自定义上传图片、录入echarts、脑图、markdown语法的编辑器

1、下载Vditor插件 npm i vditor 我的vditor版本是3.10.2&#xff0c;大家可以自行选择下载最新版本 官网&#xff1a;Vditor 一款浏览器端的 Markdown 编辑器&#xff0c;支持所见即所得&#xff08;富文本&#xff09;、即时渲染&#xff08;类似 Typora&#xff09;和分屏 …

软件必须要进行跨浏览器测试吗?包括哪些内容和注意事项?

随着互联网的普及和发展&#xff0c;用户对软件的要求越来越高。无论是在台式机、笔记本还是移动设备上&#xff0c;用户都希望能够以最好的体验来使用软件。然而&#xff0c;不同的浏览器在解析网页的方式、支持的技术标准等方面存在差异&#xff0c;这就导致了同一个网页在不…

使用J-Link Commander查找STM32死机问题

接口:PA13,PA14&#xff0c;请勿连接复位引脚。 输入usb命令这里我已经连接过了STM32F407VET6了。 再输入connect命令这里我已经默认选择了SWD接口&#xff0c;4000K速率。 可以输入speed 4000命令选择4000K速率: 写一段崩溃代码进行测试: void CashCode(void){*((volatil…

(2024,RNN,梯度消失和爆炸,记忆诅咒,重参数化和动态学习率,权重矩阵对角化,复值 RNN)梯度消失和爆炸并不是故事的结局

Recurrent neural networks: vanishing and exploding gradients are not the end of the story 公和众与号&#xff1a;EDPJ&#xff08;进 Q 交流群&#xff1a;922230617 或加 VX&#xff1a;CV_EDPJ 进 V 交流群&#xff09; 目录 0. 摘要 1. 梯度消失和梯度爆炸 2. 记…

PyCharm2024 for mac Python编辑开发

Mac分享吧 文章目录 效果一、下载软件二、开始安装1、双击运行软件&#xff08;适合自己的M芯片版或Intel芯片版&#xff09;&#xff0c;将其从左侧拖入右侧文件夹中&#xff0c;等待安装完毕2、应用程序显示软件图标&#xff0c;表示安装成功3、打开访达&#xff0c;点击【文…

深入解读一下`android.os.CountDownTimer`

简介 在 Android 开发中&#xff0c;CountDownTimer 是一个非常有用的类&#xff0c;它可以用于倒计时任务&#xff0c;比如倒计时器、限时活动等。CountDownTimer 提供了一个简单的方式来实现定时操作&#xff0c;无需我们手动管理线程和计时器。 本文将深入解析 CountDownT…

大数据------JavaWeb------Maven(完整知识点汇总)

额外知识点 IDE IDE是集成开发环境的缩写&#xff0c;它是一种软件应用程序&#xff0c;提供了编码、调试和部署软件的一站式解决方案。这些功能集成在一起&#xff0c;使开发人员能够在一个环境中完成整个软件开发过程&#xff0c;从编写代码到调试和测试&#xff0c;直到最终…

中霖教育:税务师考试通过率怎么样?

税务师考试的通过率通常在20%至30%的范围内&#xff0c;涵盖五个科目&#xff1a;《税法一》、《税法二》、《财务与会计》、《涉税服务实务》和《涉税服务相关法律》&#xff0c;成绩有效期为五年。 针对税务师备考&#xff0c;有效的学习策略至关重要。 1、熟悉各科的题型和…

什么是 SSH(安全外壳协议)以及如何工作

安全外壳协议&#xff08;Secure Shell&#xff0c;简称SSH&#xff09;&#xff0c;旨在取代未加密的协议&#xff08;如 Telnet 和 RSH&#xff09;和未受保护的文件传输协议&#xff08;如 FTP 和 RCP&#xff09;&#xff0c;在两个设备之间提供安全的加密连接。 安全外壳…

数字社交的领航者:解析Facebook的引领作用

在当今数字化社会中&#xff0c;社交网络已经成为了人们日常生活不可或缺的一部分。而在众多社交平台中&#xff0c;Facebook凭借其巨大的用户基础和创新的技术应用&#xff0c;被公认为数字社交领域的领航者之一。本文将深入解析Facebook在数字社交中的引领作用&#xff0c;探…

免费可视化工具如何提升工作效率?

免费可视化工具能为我们的工作带来什么好处&#xff1f;在如今数据密集的工作环境中&#xff0c;如何高效地处理和展示数据成为了每个行业的重要任务。传统的工具如Excel虽然强大&#xff0c;但在处理复杂数据和创建高级图表时往往显得力不从心。而免费可视化工具的出现&#x…

让DroidVNC-NG支持中文输入

DroidVNC-NG支持控制端输入内容&#xff0c;但是仅支持英文字符&#xff0c;如果需要控制输入法软键盘输入中文的话就没办法了&#xff0c;经过摸索找到了解决办法。 这个解决办法有个条件就是让DroidVNC-NG成为系统级应用&#xff08;这个条件比较苛刻&#xff09;&#xff…