当前位置: 首页 > wzjs >正文

企业如何进行网站建设国家免费培训机构

企业如何进行网站建设,国家免费培训机构,陈林设计事务所,寿光哪里做网站每个用户进程有自己的地址空间。 线程是操作系统与多线程编程的基础知识。 系统为每个用户进程创建一个 task_struct 来描述该进程:该结构体中包含了一个指针指向该进程的虚拟地址空间映射表: 实际上 task_struct 和地址空间映射表一起用来表示一个进程…

每个用户进程有自己的地址空间。

线程是操作系统与多线程编程的基础知识。
系统为每个用户进程创建一个 task_struct 来描述该进程:该结构体中包含了一个指针指向该进程的虚拟地址空间映射表:
请添加图片描述
实际上 task_struct 和地址空间映射表一起用来表示一个进程。由于进程的地址空间是私有的,因此在进程间上下文切换时,系统开销比较大,因此,为了提高系统的性能,许多操作系统规范里引入了轻量级进程的概念,也被称为线程。在同一个进程中创建的线程共享该进程的地址空间,Linux里同样用task_struct 来描述一个线程。线程和进程都参与统一的调度。

通常线程指的是共享相同地址空间的多个任务:
请添加图片描述

线程:1> 线程是轻量级的进程2> 线程的体现是函数-- 在一个进程中,多个函数通知执行(多线程的任务)3> 线程依赖于进程4> 线程是CPU调度和执行的最小单位5> 同一个进程中的线程,共享该进程的地址空间6> 多线程通过第三方的线程库来实现 -- pthread7> 线程创建的上限受栈空间影响ulimit -astack size              (kbytes, -s) 81921- 一个进程中的多个线程共享以下资源可执行的指令静态数据进程中打开的文件描述符信号处理函数当前工作目录用户ID用户组ID2- 每个线程私有的资源如下线程ID (TID) -- gettid()  pthread_self()PC(程序计数器)和相关寄存器堆栈局部变量返回地址错误号 (errno)信号掩码和优先级  0-144执行状态和属性

多线程通过第三方的线程库来实现:New POSIX Thread Library (NPTL)

  • 是早期Linux Threads的改进
  • 采用1:1的线程模型
  • 显著的提高了运行效率
  • 信号处理效率更高

接下来我们会详细的介绍线程共享资源和私有资源,还有线程库如pthread,以及线程的限制如栈空间。

线程(Thread)

线程是操作系统进行 CPU 调度和执行的最小单位,是轻量级的进程(Lightweight Process),允许多个执行流在同一个进程内并发运行。

一、线程的核心特性
  1. 轻量级进程
    • 线程共享进程的地址空间和资源,创建、切换、销毁的开销远小于进程
    • 示例:一个浏览器进程可包含多个线程(渲染线程网络线程UI线程)。
  2. 线程的体现是函数
    • 线程的执行入口是一个函数,多个线程对应多个并行执行的函数。
    • 示例代码(POSIX线程):
#include <pthread.h>
void *thread_func(void *arg) {printf("Thread ID: %lu\n", pthread_self());return NULL;
}
int main() {pthread_t tid;pthread_create(&tid, NULL, thread_func, NULL);pthread_join(tid, NULL);return 0;
}
  1. 依赖进程存在
    • 线程无法独立存在,必须依附于进程。
    • 进程终止时,所有线程会被强制终止。
  2. CPU 调度的最小单位
    • 操作系统调度器直接管理线程,而非进程。
    • 线程的优先级和调度策略可独立设置(如 SCHED_FIFO, SCHED_RR)。
  3. 共享进程地址空间
    • 同一进程的所有线程共享:
      • 代码段:可执行指令。
      • 数据段:全局变量、静态变量。
      • 堆栈:动态分配的内存。
      • 文件描述符:打开的文件、网络套接字。
  4. 第三方线程库实现
    • POSIX 线程库pthread):Linux/Unix 标准实现。
    • Windows APICreateThread 函数。
  5. 线程创建限制
    • 线程数量受 栈空间大小 限制(通过 ulimit -s 查看)。
    • 默认栈大小(Linux 通常为 8MB),可通过属性调整:
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setstacksize(&attr, 2 * 1024 * 1024); // 2MB
pthread_create(&tid, &attr, thread_func, NULL);
二、线程的共享资源与私有资源
  1. 共享资源(进程级别)
资源类型说明
可执行指令进程的代码段(.text
静态数据全局变量、静态变量(.data, .bss
文件描述符打开的文件、管道、套接字
信号处理函数signal()sigaction() 注册的处理函数
当前工作目录进程的 cwd(可通过 chdir() 修改)
用户ID和组ID进程的权限身份
  1. 私有资源(线程级别)
资源类型说明
线程ID(TID)内核级ID(gettid())或用户级ID(pthread_self()
程序计数器(PC)当前执行的指令地址
寄存器状态CPU 寄存器的当前值(如 EAX, EBX)
堆栈存储局部变量、函数调用链
局部变量函数内定义的自动变量
错误号(errno)线程独立的错误状态码
信号掩码pthread_sigmask() 设置的阻塞信号集合
调度优先级范围通常为 0(最低)到 99(实时优先级)
执行状态运行、就绪、阻塞等
三、线程与进程的对比
特性进程线程
资源开销高(独立地址空间、文件描述符)低(共享进程资源)
创建速度慢(需复制父进程资源)快(仅分配栈和少量数据结构)
通信机制复杂(管道、共享内存等)简单(共享全局变量)
容错性高(一个进程崩溃不影响其他)低(一个线程崩溃导致进程终止)
CPU 利用率低(上下文切换开销大)高(切换快速)

线程的应用场景:

  1. 高并发服务器:每个客户端连接由一个线程处理(如 Web 服务器 Apache)。
  2. 实时数据处理:数据采集线程 + 处理线程 + 存储线程(如音视频流处理)。
  3. GUI 应用程序:UI 主线程 + 后台计算线程(避免界面卡顿)。
  4. 并行计算:多线程分割任务加速计算(如矩阵运算)。

四、线程的操作(线程API都是pthread_ 开头)

  1. 创建新线程
#include <pthread.h>
typedef void *(*start_routine) (void *) //一个函数指针指向指针函数
   要求:1> 返回值类型 void * 2> 参数列表 只能有一个 void * 类型的参数int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg);参数:thread:线程的ID号attr:线程的属性 NULL 表示使用默认属性start_routine:线程处理函数 -- 专门处理多线程任务的arg:传递给线程处理函数的参数 NULL 表示不需要传参返回值:成功: 0失败:一个错误号Compile and link with -pthread.   编译线程的程序需要加 -lpthreadgcc 1-pthread_creat.c -lpthread进程的结束是判断main函数是否结束,如果main函数结束,进程会直接结束,会直接回收其他线程的内容

创建进程:

#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>#if 0int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg);参数:thread:线程的ID号attr:线程的属性 NULL 表示使用默认属性start_routine:线程处理函数 -- 专门处理多线程任务的arg:传递给线程处理函数的参数  NULL 表示不需要传参返回值:成功: 0失败:一个错误号
#endif
typedef struct
{int a;float b;
}Stu_t;
//线程处理函数:(名称自定义)
//返回值类型必须是void *
//参数列表只能有一个 void *类型的参数
void *pthread_task(void *arg)
{//printf("收到大哥的指示:%c\n",*(char *)arg);    //接收单个字符//printf("收到大哥的指示:%d\n",*(int *)arg);       //接收int数据//printf("收到大哥的指示:%s\n",(char *)arg);       //接收字符串Stu_t *temp = (Stu_t *)arg;printf("%d   %f \n",temp->a,temp->b);   //接收一个结构体return (void *)0;
}int main()
{int n = 7;char c = 'a';char str[] = "hello\n";Stu_t s1 = {10,12.34};//func();//开新线程pthread_t tid;  //接收新线程的tid//int ret = pthread_create(&tid,NULL,pthread_task,NULL ); // 这句话之后线程处理函数开始运行//int ret = pthread_create(&tid,NULL,pthread_task, &c);   //传递单个字符//int ret = pthread_create(&tid,NULL,pthread_task, &n);   //传递一个int 类型的数据//int ret = pthread_create(&tid,NULL,pthread_task, str);  //传递一个字符串int ret = pthread_create(&tid,NULL,pthread_task, &s1);    //传递一个结构体if(ret != 0){perror("pthread_create");return -1;}sleep(1);
}
  1. 线程的退出
#include <pthread.h>void pthread_exit(void *retval);
//	参数:
//		retval:遗言
//		返回值:无Compile and link with -pthread.
  1. 线程的等待收尸
#include <pthread.h>
//阻塞当前线程,等到指定线程结束
int pthread_join(pthread_t thread, void **retval);
//   参数:
//        thread:线程号
//        retval:接收线程的遗言 NULL 表示不关系
//    返回值:
//        成功: 0
//        失败:一个错误号Compile and link with -pthread.

杀死进程与收尸:

#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>#if 0int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg);参数:thread:线程的ID号attr:线程的属性 NULL 表示使用默认属性start_routine:线程处理函数 -- 专门处理多线程任务的arg:传递给线程处理函数的参数  NULL 表示不需要传参返回值:成功: 0失败:一个错误号
#endif//线程处理函数:(名称自定义)
//返回值类型必须是void *
//参数列表只能有一个 void *类型的参数
void *pthread_task(void *arg)
{int n = 7;while(n--){printf("笑死,我是你爹\n");sleep(1);}// return (void *)0;//pthread_exit(NULL);   //退出当前线程,没有遗言//pthread_exit("穿山甲到底说了啥");    //退出当前线程,有遗言static int a = 100;pthread_exit((void *)(&a));}
int main()
{int n = 7;//开新线程pthread_t tid;//开启新线程 pthread_task 采用默认属性,不传递参数int ret = pthread_create(&tid,NULL,pthread_task,NULL ); // 这句话之后线程处理函数开始运行if(ret != 0){perror("pthread_create");return -1;}while(n--){printf("我是老大\n");}//pthread_join(tid,NULL); //阻塞当前线程,等待指定tid的线程结束 NULL不关系遗言//int pthread_join(pthread_t thread, void **retval);
#if 0char *retval = NULL;    //避免野指针的出现pthread_join(tid,(void **)&retval); //接收遗言printf("%s\n",retval);
#endif#if 1int *retval;pthread_join(tid,(void **)&retval); //接收遗言printf("%d\n",*retval);
#endifprintf("------------------------------\n");pthread_exit(0);
}
  1. 线程的属性设置

分离属性:线程结束后,线程自动回收自己空间。
非分离属性(默认): 线程结束后,最后同一由 main() 线程收尸。

如何设置设置线程属性?1> 先创建线程,在设置#include <pthread.h>//将指定的线程设置为分离属性int pthread_detach(pthread_t thread);参数:thread:线程的ID号返回值:成功: 0失败:一个错误号Compile and link with -pthread.

非分离属性(默认)示例代码:

#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>#if 0int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg);参数:thread:线程的ID号attr:线程的属性 NULL 表示使用默认属性start_routine:线程处理函数 -- 专门处理多线程任务的arg:传递给线程处理函数的参数  NULL 表示不需要传参返回值:成功: 0失败:一个错误号
#endif//线程处理函数:(名称自定义)
//返回值类型必须是void *
//参数列表只能有一个 void *类型的参数
void *pthread_task(void *arg)
{printf("%ld -- 开启\n",pthread_self());    //pthread_self()获取自己的tidprintf("%ld -- 关闭\n",pthread_self());
}int main()
{//func();//开新线程pthread_t tid;int count = 0;while(1){//开启新线程 pthread_task 采用默认属性,不传递参数int ret = pthread_create(&tid,NULL,pthread_task,NULL ); // 这句话之后线程处理函数开始运行if(ret != 0){perror("pthread_create");return -1;}printf("cout  = %d\n",count ++);}
}

分离属性示例代码:

#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>#if 0int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg);参数:thread:线程的ID号attr:线程的属性 NULL 表示使用默认属性start_routine:线程处理函数 -- 专门处理多线程任务的arg:传递给线程处理函数的参数  NULL 表示不需要传参返回值:成功: 0失败:一个错误号
#endif//线程处理函数:(名称自定义)
//返回值类型必须是void *
//参数列表只能有一个 void *类型的参数
void *pthread_task(void *arg)
{printf("%ld -- 开启\n",pthread_self());    //pthread_self()获取自己的tidprintf("%ld -- 关闭\n",pthread_self());
}int main()
{//func();//开新线程pthread_t tid;int count = 0;while(1){//开启新线程 pthread_task 采用默认属性,不传递参数int ret = pthread_create(&tid,NULL,pthread_task,NULL ); // 这句话之后线程处理函数开始运行if(ret != 0){perror("pthread_create");return -1;}//int pthread_detach(pthread_t thread);pthread_detach(tid);    //将指定tid的线程变为分离属性printf("cout  = %d\n",count ++);}
}
 	2> 先设置属性,在创建线程#include <pthread.h>//设置初始属性int pthread_attr_init(pthread_attr_t *attr);参数:attr:线程属性//销毁属性int pthread_attr_destroy(pthread_attr_t *attr);#include <pthread.h>//设置线程的分离属性int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);参数:attr:线程属性detachstate:要设置的属性PTHREAD_CREATE_DETACHED:设置线程的分离属性PTHREAD_CREATE_JOINABLE:设置线程的非分离属性返回值:成功: 0失败:一个错误号Compile and link with -pthread.

pthread_attr_init.c(先设置属性,在创建线程)

#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>#if 0int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg);参数:thread:线程的ID号attr:线程的属性 NULL 表示使用默认属性start_routine:线程处理函数 -- 专门处理多线程任务的arg:传递给线程处理函数的参数  NULL 表示不需要传参返回值:成功: 0失败:一个错误号
#endif//线程处理函数:(名称自定义)
//返回值类型必须是void *
//参数列表只能有一个 void *类型的参数
void *pthread_task(void *arg)
{printf("%ld -- 开启\n",pthread_self());    //pthread_self()获取自己的tidprintf("%ld -- 关闭\n",pthread_self());
}int main()
{//1- 初始化线程属性//int pthread_attr_init(pthread_attr_t *attr);pthread_attr_t attr;    //存放线程属性的参数if(pthread_attr_init(&attr)!= 0)    //将默认属性给到attr{perror("pthread_attr_init");return -1;}//2-设置线程的分离属性//int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);
/*PTHREAD_CREATE_DETACHED:设置线程的分离属性PTHREAD_CREATE_JOINABLE:设置线程的非分离属性
*/   if(pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED)!= 0)     //将线程属性设置为分离属性{perror("pthread_attr_setdetachstate");return -1;}//开新线程pthread_t tid;int count = 0;while(1){//开启新线程 pthread_task 采用指定的属性 -- attr,不传递参数int ret = pthread_create(&tid,&attr,pthread_task,NULL ); // 这句话之后线程处理函数开始运行if(ret != 0){perror("pthread_create");return -1;}printf("cout  = %d\n",count ++);}
}

五、线程的同步以及互斥

线程同步机制
由于线程共享内存,需同步机制避免竞态条件:
多线程共享同一个进程的地址空间,优点:线程间很容易进行通信,通过全局变量实现数据共享和交换。缺点:多个线程同时访问共享对象时需要引入同步和互斥机制

同步(synchronization) 指的是多个任务(线程)按照约定的顺序相互配合完成一件事情,1968年,Edsgar Dijkstra 基于信号量的概念提出了一种同步机制,由信号量来决定线程是继续运行还是阻塞等待。

信号量代表某一类资源,其值表示系统中该资源的数量。信号量是一个受保护的变量,只能通过三种操作来访问:

  1. 初始化

  2. P操作(申请资源)

     P(S) 含义如下:if (信号量的值大于0) { 申请资源的任务继续运行;信号量的值减一;}else { 申请资源的任务阻塞;} 
    
  3. V操作(释放资源)

     V(S) 含义如下:if (没有任务在等待该资源) { 信号量的值加一;}else { 唤醒第一个等待的任务,让其继续运行}
    

注意:信号量的值为非负整数。

Posix Semaphore API

  • posix中定义了两类信号量:
    • 无名信号量(基于内存的信号量)
    • 有名信号量

pthread 库常用的信号量操作函数如下:

  • int sem_init(sem_t *sem, int pshared, unsigned int value);
  • int sem_wait(sem_t *sem); // P操作
  • int sem_post(sem_t *sem); // V操作
  • int sem_trywait(sem_t *sem);
  • int sem_getvalue(sem_t *sem, int *svalue);
线程间互斥

引入互斥(mutual exclusion)锁 的目的是用来保证共享数据操作的完整性。互斥锁主要用来保护临界资源,每个临界资源都由一个互斥锁来保护,任何时刻最多只能有一个线程能访问该资源。线程必须先获得互斥锁才能访问临界资源,访问完资源后释放该锁。如果无法获得锁,线程会阻塞直到获得锁为止。

  1. 互斥锁(Mutex)
pthread_mutex_t lock;
pthread_mutex_lock(&lock);
// 临界区
pthread_mutex_unlock(&lock);

线程的互斥操作 —— 互斥锁:

线程的互斥操作 -- 互斥锁1> 申请互斥锁#include <pthread.h>//初始化互斥锁int pthread_mutex_init(pthread_mutex_t *restrict mutex,const pthread_mutexattr_t *restrict attr);参数:mutex:互斥锁变量attr:互斥锁的属性 NULL 表示默认属性返回值:成功:0出错:-12> 上锁 然后 解锁#include <pthread.h>//给临界资源上锁int pthread_mutex_lock(pthread_mutex_t *mutex);//给临界资源解锁int pthread_mutex_unlock(pthread_mutex_t *mutex);参数:mutex:互斥锁变量返回值:成功:0失败:错误号
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <semaphore.h>pthread_mutex_t mutex1; //互斥锁变量int a = 0;
int b = 0;//线程处理函数:(名称自定义)
//返回值类型必须是void *
//参数列表只能有一个 void *类型的参数
void *pthread_task1(void *arg)
{while(1){//上锁 ---》 让其变成临界资源pthread_mutex_lock(&mutex1);/*临界区*/a++;b++;/*---------*///解锁 -- 》解除临界资源pthread_mutex_unlock(&mutex1);}
}
void *pthread_task2(void *arg)
{while(1){if(a == b){printf("a = b = %d\n",a);}else{printf("a = %d,b = %d\n",a,b);}}
}int main()
{//申请互斥锁//int pthread_mutex_init(pthread_mutex_t *restrict mutex,const pthread_mutexattr_t *restrict attr);if(pthread_mutex_init(&mutex1,NULL) == -1){fprintf(stderr,"pthread_mutex_init error\n");return -1;}//开新线程pthread_t tid1,tid2;//开启新线程 pthread_task 采用默认属性,不传递参数int ret = pthread_create(&tid1,NULL,pthread_task1,NULL ); // 这句话之后线程处理函数开始运行if(ret != 0){perror("pthread_create");return -1;}ret = pthread_create(&tid1,NULL,pthread_task2,NULL ); // 这句话之后线程处理函数开始运行if(ret != 0){perror("pthread_create");return -1;}pthread_join(tid1,NULL);pthread_join(tid2,NULL);
}
  1. 条件变量(Condition Variable)
pthread_cond_t cond;
pthread_cond_wait(&cond, &lock);  // 等待条件
pthread_cond_signal(&cond);       // 通知一个线程
  1. 信号量(Semaphore)
sem_t sem;
sem_wait(&sem);  // P操作
sem_post(&sem);  // V操作

线程的同步机制:

1- 线程的同步 --- 信号量 : 信号量的值为非负整数1> 信号量的初始化#include <semaphore.h>int sem_init(sem_t *sem, int pshared, unsigned int value);参数:sem:信号量的变量pshared:信号量的使用范围0 :线程专用非0 :进程也可以使用value:信号量的值返回值:成功:0失败:-1 ,并且设置错误号Link with -pthread.2> 执行PV操作 ---- p操作 -1#include <semaphore.h>int sem_wait(sem_t *sem);参数:sem:信号量的变量;返回值:成功:0失败:-1 ,并且设置错误号---- V操作 +1#include <semaphore.h>int sem_post(sem_t *sem);参数:sem:信号量的变量;返回值:成功:0失败:-1 ,并且设置错误号Link with -pthread.
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <semaphore.h>sem_t sem1,sem2;      //信号量的变量 最好设置为全局变量//线程处理函数:(名称自定义)
//返回值类型必须是void *
//参数列表只能有一个 void *类型的参数
void *pthread_task1(void *arg)
{while(1){printf("我是老大,都听我的\n");sem_post(&sem1); //v操作 +1//sleep(1);}
}
void *pthread_task2(void *arg)
{while(1){sem_wait(&sem1); // p操作 -1printf("我是你爹,不停你的\n");//sleep(1);}
}int main()
{//初始化信号量//int sem_init(sem_t *sem, int pshared, unsigned int value);//sem_init(变量,适用范围,初始值)sem_init(&sem1,0,0);//func();//开新线程pthread_t tid1,tid2;//开启新线程 pthread_task 采用默认属性,不传递参数int ret = pthread_create(&tid1,NULL,pthread_task1,NULL ); // 这句话之后线程处理函数开始运行if(ret != 0){perror("pthread_create");return -1;}ret = pthread_create(&tid1,NULL,pthread_task2,NULL ); // 这句话之后线程处理函数开始运行if(ret != 0){perror("pthread_create");return -1;}pthread_join(tid1,NULL);pthread_join(tid2,NULL);
}

综上。希望该内容能对你有帮助,感谢!

以上。仅供学习与分享交流,请勿用于商业用途!转载需提前说明。

我是一个十分热爱技术的程序员,希望这篇文章能够对您有帮助,也希望认识更多热爱程序开发的小伙伴。
感谢!

http://www.dtcms.com/wzjs/213206.html

相关文章:

  • 老百姓可以做监督政府的网站吗新郑网络推广外包
  • 做文案图片上什么网站十大经典广告营销案例
  • 二手书网站建设日程表微信公众号推广软文案例
  • 郑州发布最新通知南京百度关键字优化价格
  • 织梦企业 网站源码营销推广是干什么的
  • 做一个官方网站多少钱地推平台
  • 营销型网站建设的五力原则互联网项目
  • 那个网站做图片好看搜索引擎优化的工具
  • 专注网站制作淘宝怎样优化关键词
  • 网站制作前景太原百度seo排名软件
  • 国外做设计赚钱的网站网站优化排名软件哪些最好
  • 建设手机网站哪个平台比较好制作网站软件
  • 上海网站制作建设怎么样seo排名平台
  • 比特币交易网站开发今天国际新闻大事
  • 徐州商城建站系统公司怎么在网上推广
  • 网站制作常见的问题seo公司是什么意思
  • 网站如何收录快制作一个app软件需要多少钱
  • 想做一个网站怎么做推广策略有哪些方法
  • 地方性资讯门户网站app营销十大成功案例
  • dedecms 营销网站模板免费下载又有什么新病毒出现了
  • wordpress风影海南百度推广seo
  • 推广优化公司网站微信朋友圈广告怎么推广
  • 嘉兴做企业网站的公司长沙正规seo优化公司
  • 宠物网站建设总结软文网站有哪些
  • 用java怎么做购物网站重庆森林影评
  • 写作网站怎么做营销推广
  • 建筑网站排行榜个人网页设计作品模板
  • 政府新闻网站建设意见平台开发
  • 做外贸网站案例厦门百度代理公司
  • 做网站php与python网站优化排名首页