您的位置:首页 > 新闻 > 热点要闻 > 外包开发app需要多少钱_抖音代运营服务项目内容_百度高搜_武汉it培训机构排名前十

外包开发app需要多少钱_抖音代运营服务项目内容_百度高搜_武汉it培训机构排名前十

2025/2/25 9:57:12 来源:https://blog.csdn.net/FuLLovers/article/details/142961755  浏览:    关键词:外包开发app需要多少钱_抖音代运营服务项目内容_百度高搜_武汉it培训机构排名前十
外包开发app需要多少钱_抖音代运营服务项目内容_百度高搜_武汉it培训机构排名前十

一、调度

runqueue内有两个哈希表(queue[140]

struct queue{int nr_active;int bitmap[5];task_struct* queue[140];
};

⬇️

struct queue array[2]

⬇️

struct runqueue{struct queue* active;//活跃的struct queue* expired;//过期的struct queue array[2]...
};

在这里插入图片描述
调度器在执行进程调度时,需要确保公平性和效率。

1. 调度过程

(1)队列管理

  • 系统维护两个队列:activeexpired
  • 初始状态下,active队列指向array[0]expired队列指向array[1]

(2)调度情况

  • 进程运行结束:进程完成后,从active队列中移除。
  • 时间片用完但进程未结束:将进程移至expired队列。
  • 新进程产生:新进程加入active队列。

(3)队列交换

  • active队列中的进程数量逐渐减少并为空时,进行swap(&active, &expired)操作,即交换两个队列的指针。
  • 这样,原expired队列成为新的active队列,重新开始调度。

2. Linux内核O(1)调度算法

  • 优先级调度:在active队列中,按照进程的优先级进行调度,优先级高的进程先执行。
  • 公平性:通过队列交换机制,确保低优先级的进程也有机会被调度,从而实现调度机会的均等化。

bitmap[5] 共占用32×5=160个比特位(可覆盖140个位置)作为位图使用。其中每位的值为0表示无进程,为1则表示相应位置上有进程。

for(int i = 0; i < 5; ++i){if (bitmap[i] == 0) continue;//一次就可以检测32个位置else {//32个比特位中确定是哪一个位置队列是不为空的//位操作...}
}

当然可以。以下是经过优化并补充细节的专业描述:

3. Linux中的双链表结构

(1)基本结构

Linux内核中使用的双链表结构主要用于高效地管理进程和其他内核对象。该结构仅包含指向前后节点的指针,而不直接携带数据:
node实际为list_head

struct node {struct node* next; // 指向下一个节点struct node* prev; // 指向前一个节点
};

task_struct结构体中,这种双链表节点用于将进程与其他内核数据结构关联起来:

struct task_struct {// 进程的各种属性,如PID、状态等...// 链接字段,用于插入到不同的链表中struct node link;
};

为了使一个进程能够同时存在于多个数据结构中,例如全局进程列表、就绪队列或等待队列,task_struct可以包含多个这样的双链表节点:

struct task_struct {// 进程的相关属性...// 不同场景下的链接字段struct node listnode;       // 用于全局进程链表struct node queuenode;      // 用于就绪队列struct node waitnode;       // 用于等待队列...
};

通过这种方式,单个进程可以同时存在于全局链表以及任何其他需要的数据结构中,只需在task_struct中添加对应的节点字段即可。这种方法提高了灵活性,允许内核有效地管理进程的不同状态和关系。

(2)访问其他属性的原理

表达式 (struct A*) (&c - &( (struct A*) 0 -> c )) 的目的是计算结构体 A 中成员 c 的偏移量,并将其转换为一个指向结构体 A 的指针。

  1. (struct A*) 0:这是将数字0强制类型转换为指向结构体 A 的指针。这个指针并不指向实际的内存地址,它只是一个用于计算的基准点。
  2. (struct A*) 0 -> c:这里通过基准点指针访问结构体 A 的成员 c。由于基准点是一个假想的地址0,实际上并没有访问内存,而是表示了从结构体 A 的起始地址到成员 c 的偏移量。

这里的关键在于理解指针运算和结构体成员的偏移量:
(struct A*) 0:数字0被强制转换为指向 struct A 的指针。这只是一个计算上的技巧,并不是真的要访问地址0处的结构体。
(struct A*) 0 -> c:当我们使用这个指针来访问成员 c 时,编译器会计算成员 c 相对于结构体 A 起始地址的偏移量。这是编译器内部的行为,它知道每个成员在结构体中的位置,即使我们并没有创建一个实际的结构体实例。

使用 offsetof 宏来获取结构体成员的偏移量,下面是 offsetof 宏的一个典型定义:
#define offsetof(type, member) ((size_t)(&((type*)0)->member))

  1. &( (struct A*) 0 -> c ):这是取成员 c 的地址。由于指针是0,这个地址实际上就是成员 c 相对于结构体 A 起始地址的偏移量。
  2. &c:这是取实际结构体实例中成员 c 的地址。
  3. &c - &( (struct A*) 0 -> c ):这是将实际成员 c 的地址减去成员 c 的偏移量。由于我们已经通过 (struct A*) 0 -> c 计算了从结构体 A 起始地址到 c 的偏移量,这里的差值实际上就是结构体 A 起始地址的值。

#define who(type, x) ( type* (&x - ( (type*) 0 -> x ) ) )
访问其他属性:
who(struct task_struct, link) -> pri(或者pid等等)

二、命令行参数

1. 引入

main函数的参数
int argc(参数的个数), char* argv[](参数的清单)
称为命令行参数列表

#include <stdio.h>int main(int argc, char* argv[]){printf("argc: %d\n", argc);for(int i = 0; i < argc; ++i){printf("argv[%d]: %s\n", i, argv[i]);}return 0;
}
$ ./para abcdef xyz
argc: 3
argv[0]: ./para
argv[1]: abcdef
argv[2]: xyz

存在的原因:
同一个程序,可以根据命令行参数、根据选项的不同,表现出不同的功能,比如指令中选项的实现

简例:

#include <stdio.h>
#include <string.h>
int main(int argc, char* argv[])
{if(argc != 2){printf("Usage: ./code -opt\n");}else if (strcmp(argv[1], "-opt1") == 0){printf("功能1\n");}else if (strcmp(argv[1], "-opt2") == 0){printf("功能2\n");}else if (strcmp(argv[1], "-opt3") == 0){printf("功能3\n");}else{printf("默认功能\n");}return 0;
}

2. main参数的传递

输入命令 + 选项(字符串),首先被shell拿到按照空格打散,形成一张表(argv)和元素个数(argc)
命令行启动的程序,父进程都是shell
对于数据(尤其是只读的),子进程也能看到,把参数传给main函数即可
编译器、操作系统和加载器不是互相割裂的,彼此之间是有关系的

三、环境变量

1. 引入

#include <stdio.h>
#include <string.h>int main(int argc, char* argv[], char* env[])
{for(int i = 0; env[i]; ++i){printf("env[%d]: %s\n", i, env[i]);}return 0;
}

查看环境变量:

env[0]: SHELL=/bin/bash
env[1]: HISTSIZE=1000
env[2]: HISTTIMEFORMAT=%F %T root 
env[3]: PWD=/home/usr1/mylinux/F0923
env[4]: LOGNAME=usr1
env[5]: XDG_SESSION_TYPE=tty
env[6]: MOTD_SHOWN=pam
env[7]: HOME=/home/usr1
env[8]: LANG=en_US.UTF-8
......

key=value方式构建的,具有“全局”属性的变量,叫做全局变量

2. 常见的环境变量

【Q】为什么系统知道命令在/usr/bin路径下?
【A】PATH(指定命令的搜索路径)环境变量告知了shell该何处查找

usr1$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin

:是路径分隔符,PATH系统可执行文件的搜索路径集合
如果不想带路径输入命令让我的程序运行起来,可以:
(1)把可执行文件拷贝到/usr/bin目录下
(2)把自己的路径添加到PATH
追加路径:PATH=$PATH:当前路径(每次重启会重置回初始状态)
【注】如果直接输入PATH=当前路径 添加后再输入其他命令会发现其他命令找不到了,因为这种写法是覆盖式
【Q】环境变量的初始内容从何而来?
【A】开始都是在系统的配置文件中
登录 ➡️ 启动一个shell进程 ➡️ 读取用户和系统相关的环境变量的配置文件 ➡️ 形成自己的环境变量表 ➡️ 子进程

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com