linux系统调度之时间【转】

[摘要]

[En]

[abstract]

linux系统的调度过程是基于时间子系统实现的。无论判断一个系统的性能还是计算一个进程的cpu占用率等,其本质都是进程或中断等占有cpu的时间。了解linux中时间的概念,尤为重要。本文将为你剖析一下与进程和调度有关的几个关键时间。若想了解整个linux的时间子系统,请参考博文.

[背景资料]

[En]

[background]

本文的主要目的是为调度子系统的引入做好铺垫。

[En]

The main purpose of this paper is to pave the way for the introduction of the scheduling subsystem.

[文本]

[En]

[text]

在linux时间子系统一文中我们知道,linux每个时钟中断(又称tick中断)处理中都会更新进程时间,即update_process_times。所以本文把update_process_times函数作为入口点进行分析,直接上代码。

1 时钟中断中更新进程相关的时间:

普通定时器 :arch_timer_handler_phys->tick_handle_periodic->update_process_times;

高精度定时器 : tick_sched_handle->update_process_times;

void update_process_times(int user_tick)
{
struct task_struct p=current;
/
找到多核中的cpu id /
int cpu = smp_processor_id();
/
user_tick根据cpu模式判断是用户态还是内核态。linux统计时间的方式:
1 基于整个cpu的统计,user_tick表示cpu在用户态,内核态还是中断状态。此处把一个tick的时间累加到kstat_cpu(i).cpustat.

/proc/stat中的统计值是在此处统计的,表示cpu在用户态,内核态,中断中各占用多少时间,对应 stat.c(fs/proc):static int __init proc_stat_init(void);
2 基于进程的统计。linux还有一种统计时间的方法更细化,统计的是调度实体上的时间sum_exec_runtime,它在sched_clock_cpu函数中基于timer计算
/proc/pid/stat,/proc/pid/task/tid/stat中的时间是在此处统计的,它统计了一个进程/线程占用cpu的时间,对应do_task_stat实现。
/
account_process_tick(p,user_tick);
/

这负责系统中的计时器到期操作。

[En]

This is responsible for the timer expiration operation in the system.

并未真正处理,只是实现raise_softirq(TIMER_SOFTIRQ),当这个tick中断退出irq_exit时,会处理TIMER_SOFTIRQ软中断;
TIMER_SOFTIRQ软中断处理含税run_timer_softirq()中负责处理到期的定时器。
/
run_locl_timers();
/
与进程和调度用过的时间参数 */
scheduler_tick();
}
2 每个tick时钟中断中都更新调度相关的时间。

update_process_times->scheduler_tick()

/*
* This function gets called by the timer code, with HZ frequency.

  • We call it with interrupts disabled.

定时器中断时改变时间戳update_process_times->
/
void scheduler_tick(void)
{
/
处理当前中断的cpu id /
int cpu = smp_processor_id();
/
每个cpu上都有一个运行队列,运行队列rq上包含实时进程运行队列rt_rq和普通进程运行队列cfs_rq /
struct rq
rq = cpu_rq(cpu);
struct task_struct curr = rq->curr;
/
该函数为空实现:CONFIG_HAVE_UNSTABLE_SCHED_CLOCK
每个滴答时钟中断的处理方式如下:

[En]

Each tick clock interrupt is handled as follows:

sched_clock_tick()中更新sched_clock_data结构体(调用关系scheduler_tick()->sched_clock_tick())。
sched_clock_cpu()中通过sched_clock_data结构计算时间差(调用关系:scheduler_tick()->update_rq_clock()),
update_rq_clock中通过sched_cock_cpu函数计算就绪调度队列上的时间:rq->clock;
/
sched_clock_tick();
raw_spin_lock(&rq->lock);
/
更新当前调度队列rq的clock /
update_rq_clock(rq);
update_cpu_load_active(rq);
/

普通进程task_tick_fair
实时进程task_tick_rt
实时进程在task_tick_rt中检测时间片是否用完。
*/
curr->sched_class->task_tick(rq, curr, 0);
raw_spin_unlock(&rq->lock);
perf_event_task_tick();

ifdef CONFIG_SMP

rq->idle_balance = idle_cpu(cpu);
trigger_load_balance(rq, cpu);

endif

rq_last_tick_reset(rq);
}
void sched_clock_tick(void)

struct sched_clock_data *scd;

u64 now,now_gtod;

now_gtod = ktime_to_ns(ktime_get());

now = sched_clock();

scd->tick_raw = now;

scd->tick_gtod=now_gtod;

sched_clock_local(scd);//scd->clock初始化

2.1 更新运行队列上时间:

1) 时钟中断中更新:update_process_times->scheduler_tick()->update_rq_clock()

void update_rq_clock(struct rq rq)
{
s64 delta;
if (rq->skip_clock_update > 0)
return;
/

两个相邻周期调度程序之间的时间差/

[En]

The time difference between two adjacent periodic schedulers * /

delta = sched_clock_cpu(cpu_of(rq)) – rq->clock;
/
更新运行队列上的时钟:更新rq->clock_task 与rq->clock
/
rq->clock += delta;
/

此处更新rq->clock_task+=delta,默认配置不开情况rq->clock_task=rq->clock;如果CONFIG_IRQ_TIME_ACCOUNTING配置打开,则rq->clock_task需要减去中断上的时间。
因此,可以认为RQ->时钟队列时间计入每个节拍中断,甚至中断处理时间。

[En]

Therefore, it can be considered that rq- > clock queue time is counted in every tick interrupt, even the interrupt processing time.

而rq->clock_task是进程真正占用的时间,只不过很多情况下rq->clock_task=rq->clock,调度过程中使用rq->clock_task .
*/
update_rq_clock_task(rq, delta);
}
2)进程出入调度队列时更新activate_task/deactivate_task->enqueue_task/dequeue_task->update_rq_clock:

static void enqueue_task(struct rq rq, struct task_struct p, int flags)
{
update_rq_clock(rq);
sched_info_queued(p);
/
__setscheduler->
SCHED_NORMAL: enqueue_task_fair
SCHED_RR: enqueue_task_rt
/
p->sched_class->enqueue_task(rq, p, flags);
}
static void dequeue_task(struct rq rq, struct task_struct p, int flags)
{
update_rq_clock(rq);
sched_info_dequeued(p);
p->sched_class->dequeue_task(rq, p, flags);
}
/wake_up_new_task->/
void activate_task(struct rq rq, struct task_struct p, int flags)
{
if (task_contributes_to_load(p))
rq->nr_uninterruptible–;
/
__setscheduler-> enqueue_task_fair /enqueue_task_rt
/
enqueue_task(rq, p, flags);
}
void deactivate_task(struct rq rq, struct task_struct p, int flags)
{
if (task_contributes_to_load(p))
rq->nr_uninterruptible++;
dequeue_task(rq, p, flags);
}
2.2 更新实时进程运行队列上调度相关的时间:

1)与进程调度有关的时间存放在如下结构体,一般task_struct结构中se表示sched_entity(如:current->se.exex_start)

struct sched_entity {
u64 exec_start;
u64 sum_exec_runtime;
u64 vruntime;
u64 prev_sum_exec_runtime;
}
其中 实时进程一般只使用exec_start和sum_exec_runtime;普通进程中这几个成员变量都会被使用.sched_entity中时间的初始化函数:

staticvoid __sched_fork(struct task_struct p)
{
/
se是普通进程的调度实体struct sched_entity /
/

有关说明,请参见下文

[En]

See below for explanation

/
p->se.exec_start = 0;
/
进程执行的总时间大小/
p->se.sum_exec_runtime = 0;
/

进程上次运行的总时间,即唤醒时间。调度进程选择下一个进程最初是

[En]

The total time the process was last run, that is, the wake-up time. The scheduling process chooses that the next process is initially a

se.sum_exec_runtime,
该进程上次获取CPU的时间:

[En]

The last time the process obtained the cpu:

sum_exec_runtime-prev_sum_exec_runtime
/
p->se.prev_sum_exec_runtime = 0;
p->se.nr_migrations = 0;
/
进程在一个调度周期内的虚拟调度时间 */
p->se.vruntime = 0;
}
2)update_process_times->scheduler_tick()->task_tick_rt()

/
定时器中断时更新实时进程时间update_process_times->scheduler_tick->:
/
static void task_tick_rt(struct rq rq, struct task_struct p, int queued)
{
struct sched_rt_entity rt_se = &p->rt;
/

更新实时流程相关统计时间

[En]

Update real-time process related statistical time

/
update_curr_rt(rq);
watchdog(rq, p);
/

* RR tasks need a special form of timeslice management.

  • FIFO tasks have no timeslices.

/
/

检查SCHED_RR进程时间片是否用光;SCHED_FIFO只有主动放弃CPU使用权;
/
if (p->policy != SCHED_RR)
return;
/

时间片减一,如果时间没有结束,则直接返回

[En]

Time slice minus one, if the time is not finished, it will be returned directly

否则再次分配时间片,加入队列尾部,设置调度标记 TIF_NEED_RESCHED
/
if (–p->rt.time_slice)
return;
/

实时进程SCHED_RR
初始时间片为100 ms,即time_slice=10个时钟中断
/
p->rt.time_slice = sched_rr_timeslice;
/

* Requeue to the end of queue if we (and all of our ancestors) are the
* only element on the queue
/
for_each_sched_rt_entity(rt_se) {
if (rt_se->run_list.prev != rt_se->run_list.next) {
/

如果时间片耗尽,则把实时进程SCHED_RR的运行实体从active优先级队列上删除,如此schedule调度过程无法
系统调度器通过运行实体找到进程p进行调度来实现。

[En]

The system scheduler is realized by running the entity to find the process p for scheduling.

那么进程p何时能重新加入调度队列呢?例如wake_up_process过程可以重新入队列,具体可参照调度子系统介绍
/
requeue_task_rt(rq, p, 0);
/
该标记表示需要重新调度 */
set_tsk_need_resched(p);
return;
}
}
}
3)实时进程统计时间更新:update_process_times->scheduler_tick()->task_tick_rt()->update_curr_rt()

此时更新实时进程占有cpu的总时间se.sum_exec_runtime和一个tick间隔内进程开始执行的时间se.exec_start.

/
* Update the current task’s runtime statistics. Skip current tasks that
* are not in our scheduling class.

/
static void update_curr_rt(struct rq
rq)
{
struct task_struct curr = rq->curr;
struct sched_rt_entity
rt_se = &curr->rt;
struct rt_rq rt_rq = rt_rq_of_se(rt_se);
u64 delta_exec;
if (curr->sched_class != &rt_sched_class)
return;
/

exec_start分析:
1)exec_start表示进程在一个时钟中断间隔内开始运行的时间,主要用于在时钟中断中计算时间差,
该时间差主要用于计算进程获取cpu的时间(se.sum_exec_runtime累加该时间差:update_curr : rq->clock_task-exec_start),
2) 此时clock_task为时钟中断开始时间,exec_start可以为之前时钟中断中任一时间,且不必是时钟中断开始的时间点。
exec_start在每个tick中断中都更新为队列时间rq->clock_task.

3) 时钟中断到来时clock_task先在update_rq_clock更新。然后再用clock_task减去exec_start即获取当前进程在一个时钟中断中获取到cpu的时间。
如果exec_start恰好等于上一个时钟中断时队列上时间clock_task,则表示进程在这个时钟中断中一直占有cpu,未发生调度。
delta_exec分析:
delta_exec表示进程在一个时钟周期内,所获得的cpu执行权的时间。 把delta_exec累加,就是进程获取cpu的总时间
注意此处使用rq->clock_task而不是rq->clock,注意update_rq_clock中二者区别。
*/
delta_exec = rq->clock_task – curr->se.exec_start;
if (unlikely((s64)delta_exec

1) tick中断处理中的更新: update_process_times->scheduler_tick()->task_tick_fair()->entity_tick->update_curr()

static void update_curr(struct cfs_rq cfs_rq)
{
struct sched_entity
curr = cfs_rq->curr;
u64 now = rq_of(cfs_rq)->clock_task;
unsigned long delta_exec;
if (unlikely(!curr))
return;
/
* Get the amount of time the current task was running
* since the last time we changed load (this cannot
* overflow on 32 bits):
/
/
此处参考update_curr_rt中对exec_start的解释;
/
delta_exec = (unsigned long)(now – curr->exec_start);
if (!delta_exec)
return;
__update_curr(cfs_rq, curr, delta_exec);
/更新进程下次运行的起始时间
如果它被抢占,它将在下一次计划时更新。

[En]

If it is preempted, it will be updated the next time it is scheduled.

/
curr->exec_start = now;
if (entity_is_task(curr)) {
struct task_struct *curtask = task_of(curr);
trace_sched_stat_runtime(curtask, delta_exec, curr->vruntime);
cpuacct_charge(curtask, delta_exec);
account_group_exec_runtime(curtask, delta_exec);
}
更新当前进程运行时间统计数据update_curr()->__update_curr()

/*
* Update the current task’s runtime statistics. Skip current tasks that
* are not in our scheduling class.

/
static inline void __update_curr(struct cfs_rq
cfs_rq, struct sched_entity curr,
unsigned long delta_exec)
{
unsigned long delta_exec_weighted;
schedstat_set(curr->statistics.exec_max,
max((u64)delta_exec, curr->statistics.exec_max));
/
更新该进程获得cpu执行权的总时间 ,可参考update_curr_rt函数中sum_exec_runtime累计处的解释。
此处更新进程下一次的运行时间:表示进程在一个时钟中断内开始运行的时间 时钟中断到来时clock_task先在update_rq_clock更新。
然后再用clock_task减去exec_start即获取当前进程在一个时钟中断中获取到cpu的时间。如果exec_start恰好等于上一个时钟中断时
队列上时间clock_task,则表示进程在这个时钟中断中未发生调度。
/
curr->sum_exec_runtime += delta_exec;
schedstat_add(cfs_rq, exec_clock, delta_exec);
/

calc_delta_fair用来将真实时间转化为虚拟时间。进程的优先级不同,它在系统中的地位(权重)也不同,
进程的优先级越高,其虚拟时间就越慢。

[En]

The higher the priority of a process, the slower its virtual time goes.

/
delta_exec_weighted = calc_delta_fair(delta_exec, curr);
/
更新该进程获得cpu执行权的虚拟时间*/
curr->vruntime += delta_exec_weighted;
update_min_vruntime(cfs_rq);
}
2)无论普通进程还是实时进程,都会在选择下一进程时更新一个进程在一个时钟中断中开始执行的时间exec_start,下面以

普通进程为例进行介绍pick_next_task_fair->set_next_entity():

ps:实时进程在pick_next_task_rt()->__pick_next_task_rt()中更新se.exec_start;

static void set_next_entity(struct cfs_rq cfs_rq, struct sched_entity se)
{
/ ‘current’ is not kept within the tree. /
if (se->on_rq) {
/*
* Any task has to be enqueued before it get to execute on
* a CPU. So account for the time it spent waiting on the
* runqueue.

/
update_stats_wait_end(cfs_rq, se);
__dequeue_entity(cfs_rq, se);
}
/

update_stats_curr_start()函数实现:se->exec_start =rq_of(cfs_rq)->clock_task
调度器在选择下一个进程执行时,会更新exec_start为队列时间rq->clock_task
*/
update_stats_curr_start(cfs_rq, se);
cfs_rq->curr = se;

ifdef CONFIG_SCHEDSTATS

/
* Track our maximum slice length, if the CPU’s load is at
* least twice that of our own weight (i.e. dont track it
* when there are only lesser-weight tasks around):
/
if (rq_of(cfs_rq)->load.weight >= 2*se->load.weight) {
se->statistics.slice_max = max(se->statistics.slice_max,
se->sum_exec_runtime – se->prev_sum_exec_runtime);

endif

/
prev_sum_exec_runtime表示进程截止目前获取cpu的时间(即执行时间);
可以使用sum_exec_runtime- prev_sum_exec_runtime计算进程最近一次调度内获取cpu使用权的时间。
不过sum_exec_runtime是使用exec_start计算出的时间差的累加。
/
se->prev_sum_exec_runtime = se->sum_exec_runtime;
}
2.4 以上讨论了进程与调度相关时间的更新,可以关注三个方面:

1) tick中断处理过程中的更新,主要通过update_rq_clock函数更新调度队列上的时间rq->clock_task;

通过task_tick_rt/task_tick_fair更新进程在一个时钟中断内开始执行的时间exec_start和进程执行的总时间,sum_exec_runtime;

2) 出入调度队列时,也会更新调度队列上的时间rq->clock_task,schedule调度过程也可能更新队列时间。

3) 无论普通进程还是实时进程,都会在选择下一进程时更新一个进程在一个时钟中断中开始执行的时间exec_start。

[摘要]

[En]

[summary]

本文讨论了在每个滴答时钟中断中与进程和调度相关的时间的更新,为后续调度子系统的引入奠定了基础。

[En]

This paper discusses the update of the time related to the process and scheduling in each tick clock interrupt, laying the groundwork for the subsequent introduction of the scheduling subsystem.

注:本文讨论的时间不是墙上的时间(例如,年、月、日的时间),而是运行时间。例如,如果程序运行时间为1秒,则时间戳为1秒。

[En]

Note: the time discussed in this article is not the time on the wall (for example, the time of the year, month and day), but the running time. For example, if a program runs for 1s, the timestamp is 1s.

而不是某个年份、某个月份、某个时间等等。

[En]

Not a certain year, a certain month, a certain time, and so on.

[其他]

[En]

[other]

1 查看进程时间的方法:

void show_taskTime(struct task_struct tsk)
{
unsigned long long fork_time;
unsigned long long new_start_time;
unsigned long long sum_exec_runtime;
unsigned long long prev_sum_exec_runtime;
unsigned long long curr_fsum_exec_runtime;
int policy;
/
以下时间:单位ns;从0开始累计/
/
进程创建的时间点; /
fork_time=(unsigned long long)tsk->real_start_time.tv_sec
1000000000+
+ tsk->real_start_time。tv_nsec;
/ 进程最近一次开始执行的时间点 /
new_start_time=tsk->se.exec_start;
/进程一共执行(即获取到cpu)的时间长度/
sum_exec_runtime=tsk->se.sum_exec_runtime;
/进程上一次一共执行的时间长度;注意在schedule选择下一进程时,
下一进程tsk->se.prev_sum_exec_runtime初始化为sum_exec_runtime;
而当前进程的prev_sum_exec_runtime是在之前切换到当前进程时初始化的;
/
prev_sum_exec_runtime=tsk->se.prev_sum_exec_runtime;
/当前进程最近一次获取到cpu的时间长度;/
curr_sum_exec_runtime=tsk->se.sum_exec_runtime-tsk->se.prev_sum_exec_runtime;
policy=tsk->policy;
printk(“[%s_%d_%d:%llu_%llu_%llu_%llu_%llu]\n”,tsk->comm,tsk->pid,policy,
fork_time,new_start_time,sum_exec_runtime,prev_sum_exec_runtime,
curr_sum_exec_runtime);
}
2 查看调试信息方法:

void show_debugInfo(void)
{
/查看当前进程的执行时间/
show_taskTime(current);
/查看系统内存使用情况/
show_mem(0);
/查看当前进程的栈/
show_stack(current,NULL);
}
3 为计算进程最近一次获取cpu的时间长度,需要使用prev_sum_exec_runtime参数,而 对实时进程来说,没有使用task->se.prev_sum_exec_runtime,所以需要修改kernel代码如下:(注意如果是当前进程,则sum_exec_runtime-prev_sum_exec_runtime计算的是当前进程获取cpu以来的执行时间)

/schedule->pick_next_task_rt->_pick_next_task_rt选择下一进程时/

static struct task_struct _pick_next_task_rt(struct rq rq)
{
p->se.exec_start=rq->clock_task;
/ 添加如下代码 /
p->se.prev_sum_exec_runtime=p->se.sum_exec_runtime;
/end/
return p;
}
【c标准接口】

times()函数: 系统调用所在文件 kernel/sys.c;

Linux内核中的jiffies及其作用介绍及jiffies等相关函数详解;

使用系统sched_clock计算时间:

static void update_time_stamp(void)
{
unsigned long long timeNow = 0;
unsigned long long timeInc = 0;
static unsigned long long preTimeStamp = 0;
static unsigned long long timePtsNs = 0;
static unsigned long long timePts = 0;//返回ns

timeNow = sched_clock(); //返回ns
//64bit溢出
if(preTimeStamp > timeNow)
{
timeInc = (0xFFFFFFFFFFFFFFFF-preTimeStamp)+timeNow;
}
else
{
timeInc = timeNow – preTimeStamp;
}
timeInc += timePtsNs;//timePtsNs为上一次计算的精度损失.timePts为毫秒级,因此有损失,需要在增量timeInc上加timePtsNs
/timePtsNs为除后余数;do_div计算后timeInc为除后结果:毫秒/
timePtsNs = do_div(timeInc,1000000);
timePts = timePts + timeInc; //timepts为要获取的ms时间戳
preTimeStamp = timeNow;

return ;
}
sched_clock->sched_clock_func=sched_clock_32->read_sched_clock()

read_sched_clock初始化可以在setup_sched_clock中完成;

如1arch/arm/mach-xx/timer.c中通过setup_sched_clock设置(read_sched_clock=xx_read_sched_clock)

xx_read_sched_clock实现读定时器.

2 sched_clock_register(arch_timer_read_counter);(read_sched_clock=arch_timer_read_counter)

中断的负载均衡:

[En]

Interrupted load balancing:

1) echo 4 > /proc/irq/49/smp_affinity
4=0100 表示bit3=1;即49号中断在cpu2上处理;
您可以通过cat/proc/interrupts查看中断号

[En]

You can view the interrupt number through cat / proc/interrupts

您可以通过cat/proc/softirqs查看中断数

[En]

You can view the number of interrupts through cat / proc/softirqs

进程的负载均衡:

[En]

Load balancing of processes:

cat /proc/loadavg 查看负载均衡参数;uptime命令也可以查看.

loadavg:表示系统的平均负荷;
参考文章:平均负载

[En]

Reference article: load average

top -d 1 查看进程cpu占用率
类型c:查看不同核;类型H:查看线程CPU占用率

[En]

Type c: view different cores; type H: view thread cpu occupancy

在linux下,top -H查看线程情况,包括CPU,内存等占用情况。

进入顶层环境后,可以使用P按CPU排序,使用M按内存排序。

[En]

After entering the top environment, you can use P to sort by CPU and M to sort by memory.

cpu stall

进程和线程的时间:/proc/id/sched;/proc/id/task/tid/sched

[En]

Time of processes and threads: / proc/pid/sched; / proc/pid/task/tid/sched

[En]

版权声明:本文为CSDN博主「eleven_xiy」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/eleven_xiy/article/details/71175347

Original: https://www.cnblogs.com/sky-heaven/p/16458715.html
Author: sky-heaven
Title: linux系统调度之时间【转】

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/7034/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • [svc]sed&awk过滤行及sed常用例子

    – sed过滤行 sed ‘2p’ sed ‘2,5p’ sed ‘2p;3p;4p’ – awk&#x8…

    Linux 2022年8月26日
    0270
  • 自动化集成:Pipeline整合Docker+K8S

    前言:该系列文章,围绕持续集成:Jenkins+Docker+K8S相关组件,实现自动化管理源码编译、打包、镜像构建、部署等操作; 本篇文章主要描述流水线集成K8S用法。 一、背景…

    Linux 2022年9月10日
    0200
  • Ubuntu 添加根证书

    $sudo cp 证书路径.crt /usr/local/share/ca-certificates$sudo update-ca-certificates Original: h…

    Linux 2022年8月26日
    0240
  • wifi配网

    一、概述 “配网”指的是,外部向WiFi模块提供SSID和密码,以便Wi-Fi模块可以连接指定的热点或路由器并加入后者所建立的相关Wi-Fi网络。 WiFi…

    2022年8月11日
    0390
  • ubuntu安装svn manager

    环境:系统ubuntu14.04 0. 更新软件库 1. 安装apache,svn,svn的apache模块 2. 创建svn版本库的服务器端路径和配置文件 3. 映射到apach…

    Linux 2022年8月26日
    0270
  • 【转载】Tomcat运行原理剖析

    转自:https://mp.weixin.qq.com/s/UnaPAbSq5JU1NhFlsASTew 本文的知识点分为: Server、Service、Connector、Co…

    2022年8月26日
    0290
  • ubuntu安装Kubernetes1.20.0

    一、概述 由于业务需求,需要安装版本比较高的k8s,比如:1.20.0 二、环境介绍 操作系统:ubuntu-18.04.6-server-amd64 配置:2核3g ip地址:1…

    2022年8月26日
    0270
  • Linux常用软件

    我的工作是服务器 存储 云计算方面的实施运维工程师,已经用Linux系统作为笔记本电脑的主系统多年了,以前完全是为了个性和装比,时间长了就是一种习惯,年纪也大了也不再有那么多虚荣心…

    Linux 2022年8月24日
    0380
  • Visual Studio 2022 git error Unable to negotiate with xx.xxx.xxxx port 22: no matching host key type found. Their offer: ssh-rsa

    前言 前两天因为升级了Git导致git提交拉取的时候都提示下面这个异常,然后经过一番折腾以后终于把这个问题解决了。但是今天我升级了下Visual Studio 2022将其升级到了…

    Linux 2022年8月30日
    0220
  • linux下禁止root用户登录,修改远程ssh登录端口号

    禁止root用户登录 因为安全需要,我们在Linux下要把root用户禁止远程登录,然后用普通用户登录, 通过su – root切换到root 可以通过修改/etc/s…

    2022年8月20日
    0290
  • Linux shell将字符串转化为数组

    [本文出自天外归云的博客园] 在Linux shell中,如何将一个字符串转化为数组? 原文:https://www.golinuxcloud.com/bash-split-str…

    Linux 2022年8月26日
    0270
  • 002 Linux 文件与目录命令的必会姿势!

    文件及目录的路径切换、显示、创建、复制、移动和删除操作的常用姿势,必会!因为这些命令是使用 Linux 系统进行工作的基础,是摆脱小白的第一步,是构建大厦的基石!发现锅锅真是个话痨…

    Linux 2022年9月10日
    0230
  • PostgreSQL:在Linux系统上面安装PostgreSQL数据库

    一、准备工作 这里使用的Linux操作系统是Centos7,选择在虚拟机上面装Centos7系统,然后在虚拟机上面安装PostgreSQL。 二、安装PostgreSQL 2.1、…

    Linux 2022年8月24日
    0690
  • docker 安装redis

    1: 搜索镜像, docker search redis2:&#xA0;<strong>docker pull redis:6.0.6</strong&g…

    Linux 2022年9月14日
    0190
  • Git清除本地缓存

    2.清除缓存 如果在开发的过程中添加或者修改了.gitignore文件,那么它可能不会生效,因为一些需要忽略的文件已经加入了git的追踪列表中,可以通过清除git缓存来使新的.gi…

    Linux 2022年8月30日
    0230
  • linux查看及修改文件权限以及相关

    linux查看及修改文件权限以及相关 查看文件权限的语句: 在终端输入:ls -l xxx.xxx (xxx.xxx是文件名)那么就会出现相类似的信息,主要都是这些:-rw-rw-…

    Linux 2022年8月11日
    0410
  • Linux 配置Java环境变量

    前言:请各大网友尊重本人原创知识分享,谨记本人博客: 南国以南i 注:目前在官网下载的时候需要登陆,这边分享一个账号,方便下载 [En] Note: at present, you…

    Linux 2022年9月10日
    0240
  • Ubuntu MP4转MP3 软件:soundconverter

    sudo apt-get install soundconverter 非常实用的小软件。 Original: https://www.cnblogs.com/yaos/p/141…

    Linux 2022年8月26日
    0520
  • 小文件、nginx、Redis、Moosefs

    现在有3KW的数据,单条数据都很小的,如果按key-value来看的话,key就是32位的MD5字符串,value按平均算大概是100字节左右。 现在需要将这些数据做缓存以在高并非…

    Linux 2022年9月14日
    0240
  • linux备份数据mysql

    到mysql安装目录下的bin: ./mysqldump -u root -p ebuy_mgt > /home/2017backup.sql 弱水_穿云天 Original…

    Linux 2022年8月26日
    0390
  • javascript按字节截取标题中字符串

    让后台程序截一下,又各种推托,让后台按字节截一下更是和要了后台老命一样,最后可能只会安字符长度给你截一下,最后不好看,对不齐,还是回头整CSS、调兼容; 有以上有感触的前端同学默默…

    Linux 2022年8月20日
    0300
  • 如何利用github搭建个人网站

    一、博客 点击创建仓库 点击设置 里面放入 index.html 即可 点到为止 posted @2021-01-20 17:28 十色 阅读(230 ) 评论() 编辑 Orig…

    Linux 2022年8月30日
    0300
  • docker:alpine使用logrotate切割日志

    最近在交付项目的时候使用了docker,大家都知道日志是项目定位问题的重要依据,但如果一开始项目本身没有对日志进行合理切割那就会导致长时间运行的项目日志文件大得编辑器打不开的情况。…

    Linux 2022年9月10日
    0180
  • windows和linux cli模式支持多个php版本

    2022年2月22日09:02:00 一般来说服务器上会有多个版本的php,提供运行环境 制作多个只需要做多个软链接即可: windows下也是可以的,很多时候我们需要使用多个版本…

    Linux 2022年8月26日
    0350
  • Linux Shell 截取字符串

    shell中截取字符串的方法很多 下面用几个例子展示一下: 语法: 示例代码: 执行结果: 语法: 示例代码: 执行结果: 语法: 示例代码: 执行结果: 语法: 示例代码: 执行…

    Linux 2022年8月24日
    0320
  • 多线程/哈希slot/集群

    io多线程 以前的redis是单线程模型,其实就是多路复用机制,知道多路复用的来一波6,我们在架构师课程中讲过,那么netty也有,看过老师相关课程的也应该知道。这里不多说了。 R…

    Linux 2022年9月14日
    0160

发表回复

登录后才能评论
免费咨询
免费咨询
扫码关注
扫码关注
联系站长

站长Johngo!

大数据和算法重度研究者!

持续产出大数据、算法、LeetCode干货,以及业界好资源!

2022012703491714

微信来撩,免费咨询:xiaozhu_tec

分享本页
返回顶部