【Linux笔记】Linux进程概念与进程状态

news2024/11/23 16:59:07

【Linux笔记】Linux进程概念与进程状态

  • 一、什么是进程
    • 1.1、进程的概念
    • 1.2、进程的描述
  • 二、关于进程的一些基本操作
    • 2.1、查看进程
    • 2.2、杀进程
    • 2.3、获取进程id
    • 2.4、创建进程
  • 三、进程状态
    • 3.1、普适操作系统中的进程状态
    • 3.2、具体到Linux操作系统中的进程状态
  • 四、僵尸进程和孤儿进程
    • 4.1、僵尸进程
    • 4.2、孤儿进程
  • 五、进程的优先级
    • 5.1、查看进程的优先级
    • 5.2、怎样修改进程的优先级

一、什么是进程

1.1、进程的概念

进程的概念:

进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配的基本单位,是操作系统结构的基础。在早期面向进程设计的计算机结构中,进程是程序的基本执行实体;在当代面向线程设计的计算机结构中,进程是线程的容器。程序是指令、数据及其组织形式的描述,进程是程序的实体。

通常在一些计算机或操作系统的书籍上也会这样告诉我们:进程是被加载到内存中的程序,或者运行起来的程序就叫做进程。

1.2、进程的描述

而进程再被加载到内存中后,操作系统就一定要对其进行管理,而在操作系统看来对程序的管理本质上就是对程序数据的管理,所以操作系统就会从这些程序中抽象出一些共有属性来构建出一个结构体,然后为每一个进程都创建一个这样的结构体对象。
然后操作系统对进程的管理就转化成了对这些结构体对象的管理了,在操作系统中,这个用于描述和组织进程的东西被称为 进程控制块——PCB。

而进程控制块在不同的操作系统中的结构和名称也可能不一样,具体到Linux操作系统中的进程控制块是task_struct,它是Linux内核中的一种数据结构,其包含的内如大致如下:

标示符: 描述本进程的唯一标示符,用来区别其他进程。
状态: 任务状态,退出代码,退出信号等。
优先级: 相对于其他进程的优先级。
程序计数器: 程序中即将被执行的下一条指令的地址。
内存指针: 包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针
上下文数据: 进程执行时处理器的寄存器中的数据[
I/O状态信息: 包括显示的I/O请求,分配给进程的I/O设备和被进程使用的文件列表。
记账信息: 可能包括处理器时间总和,使用的时钟数总和,时间限制,记账号等。
其他信息

task_struct的源码肯定是非常复杂的,但没关系我们可以先了解一下。

我们可以来看看对应的task_struct的源码:

struct task_struct {
	/*
	 * 进程状态。
	 */
	volatile long state;	/* -1 unrunnable, 0 runnable, >0 stopped */
	/*
	 * 进程的基本信息。
	 */
	struct thread_info *thread_info;
	atomic_t usage;
	unsigned long flags;	/* per process flags, defined below */
	unsigned long ptrace;

	int lock_depth;		/* Lock depth */

	/*
	 * 进行的动态优先权和静态优先权
	 */
	int prio, static_prio;
	/*
	 * 进程所在运行队列。每个优先级对应一个运行队列。
	 */
	struct list_head run_list;
	/*
	 * 指向当前运行队列的prio_array_t
	 */
	prio_array_t *array;

	/*
	 * 进程的平均睡眠时间
	 */
	unsigned long sleep_avg;
	/*
	 * timestamp:进程最近插入运行队列的时间。或涉及本进程的最近一次进程切换的时间
	 * last_ran:最近一次替换本进程的进程切换时间。
	 */
	unsigned long long timestamp, last_ran;
	/*
	 * 进程被唤醒时所使用的代码。
	 * 0:进程处于TASK_RUNNING状态。
	 * 1:进程处于TASK_INTERRUPTIBLE或者TASK_STOPPED状态,而且正在被系统调用服务例程或内核线程唤醒。
	 * 2:进程处于TASK_INTERRUPTIBLE或者TASK_STOPPED状态,而且正在被ISR或者可延迟函数唤醒。
	 * -1:表示从UNINTERRUPTIBLE状态被唤醒
	 */
	int activated;

	/*
	 * 进程的调度类型:sched_normal,sched_rr或者sched_fifo
	 */
	unsigned long policy;
	/*
	 * 能执行进程的CPU的位掩码
	 */
	cpumask_t cpus_allowed;
	/*
	 * time_slice:在进程的时间片中,还剩余的时钟节拍数。
	 * first_time_slice:如果进程肯定不会用完其时间片,就把该标志设置为1。
	 *
	 * Dagger-axe注:目的为加速子进程的返回,防止内存中进程过多。
	 */
	unsigned int time_slice, first_time_slice;

#ifdef CONFIG_SCHEDSTATS
	struct sched_info sched_info;
#endif

	/*
	 * 通过此链表把所有进程链接到一个双向链表中。
	 */
	struct list_head tasks;
	/*
	 * ptrace_list/ptrace_children forms the list of my children
	 * that were stolen by a ptracer.
	 */
	/*
	 * 链表的头。该链表包含所有被debugger程序跟踪的P的子进程。
	 */
	struct list_head ptrace_children;
	/*
	 * 指向所跟踪进程的实际父进程链表的前一个下一个元素。
	 */
	struct list_head ptrace_list;

	/*
	 * mm:指向内存区描述符的指针
	 */
	struct mm_struct *mm, *active_mm;

/* task state */
	struct linux_binfmt *binfmt;
	long exit_state;
	int exit_code, exit_signal;
	int pdeath_signal;  /*  The signal sent when the parent dies  */
	unsigned long personality;
	/*
	 * 进程发出execve系统调用的次数。
	 */
	unsigned did_exec:1;
	/*
	 * 进程PID
	 */
	pid_t pid;
	/*
	 * 线程组领头线程的PID。
	 */
	pid_t tgid;
	/* 
	 * pointers to (original) parent process, youngest child, younger sibling,
	 * older sibling, respectively.  (p->father can be replaced with 
	 * p->parent->pid)
	 */
	/*
	 * 指向创建进程的进程的描述符。
	 * 如果进程的父进程不再存在,就指向进程1的描述符。
	 * 因此,如果用户运行一个后台进程而且退出了shell,后台进程就会成为init的子进程。
	 */
	struct task_struct *real_parent; /* real parent process (when being debugged) */
	/*
	 * 指向进程的当前父进程。这种进程的子进程终止时,必须向父进程发信号。
	 * 它的值通常与real_parent一致。
	 * 但偶尔也可以不同。例如:当另一个进程发出监控进程的ptrace系统调用请求时。
	 */
	struct task_struct *parent;	/* parent process */
	/*
	 * children/sibling forms the list of my children plus the
	 * tasks I'm ptracing.
	 */
	/*
	 * 链表头部。链表指向的所有元素都是进程创建的子进程。
	 */
	struct list_head children;	/* list of my children */
	/*
	 * 指向兄弟进程链表的下一个元素或前一个元素的指针。
	 */
	struct list_head sibling;	/* linkage in my parent's children list */
	/*
	 * P所在进程组的领头进程的描述符指针。
	 */
	struct task_struct *group_leader;	/* threadgroup leader */

	/* PID/PID hash table linkage. */
	/*
	 * PID散列表。通过这四个表,可以方便的查找同一线程组的其他线程,同一会话的其他进程等等。
	 */
	struct pid pids[PIDTYPE_MAX];

	struct completion *vfork_done;		/* for vfork() */
	/*
	 * 子进程在用户态的地址。这些用户态地址的值将被设置或者清除。
	 * 在do_fork时记录这些地址,稍后再设置或者清除它们的值。
	 */
	int __user *set_child_tid;		/* CLONE_CHILD_SETTID */
	int __user *clear_child_tid;		/* CLONE_CHILD_CLEARTID */

	/*
	 * 进程的实时优先级。
	 */
	unsigned long rt_priority;
	/*
	 * 以下三对值用于用户态的定时器。当定时器到期时,会向用户态进程发送信号。
	 * 每一对值分别存放了两个信号之间以节拍为单位的间隔,及定时器的当前值。
	 */
	unsigned long it_real_value, it_real_incr;
	cputime_t it_virt_value, it_virt_incr;
	cputime_t it_prof_value, it_prof_incr;
	/*
	 * 每个进程的动态定时器。用于实现ITIMER_REAL类型的间隔定时器。
	 * 由settimer系统调用初始化。
	 */
	struct timer_list real_timer;
	/*
	 * 进程在用户态和内核态下经过的节拍数
	 */
	cputime_t utime, stime;
	unsigned long nvcsw, nivcsw; /* context switch counts */
	struct timespec start_time;
/* mm fault and swap info: this can arguably be seen as either mm-specific or thread-specific */
	unsigned long min_flt, maj_flt;
/* process credentials */
	uid_t uid,euid,suid,fsuid;
	gid_t gid,egid,sgid,fsgid;
	struct group_info *group_info;
	kernel_cap_t   cap_effective, cap_inheritable, cap_permitted;
	unsigned keep_capabilities:1;
	struct user_struct *user;
#ifdef CONFIG_KEYS
	struct key *session_keyring;	/* keyring inherited over fork */
	struct key *process_keyring;	/* keyring private to this process (CLONE_THREAD) */
	struct key *thread_keyring;	/* keyring private to this thread */
#endif
	int oomkilladj; /* OOM kill score adjustment (bit shift). */
	char comm[TASK_COMM_LEN];
/* file system info */
	/*
	 * 文件系统在查找路径时使用,避免符号链接查找深度过深,导致死循环。
	 * link_count是__do_follow_link递归调用的层次。
	 * total_link_count调用__do_follow_link的总次数。
	 */
	int link_count, total_link_count;
/* ipc stuff */
	struct sysv_sem sysvsem;
/* CPU-specific state of this task */
	struct thread_struct thread;
/* filesystem information */
	/*
	 * 与文件系统相关的信息。如当前目录。
	 */
	struct fs_struct *fs;
/* open file information */
	/*
	 * 指向文件描述符的指针
	 */
	struct files_struct *files;
/* namespace */
	struct namespace *namespace;
/* signal handlers */
	/*
	 * 指向进程的信号描述符的指针
	 */
	struct signal_struct *signal;
	/*
	 * 指向进程的信号处理程序描述符的指针
	 */
	struct sighand_struct *sighand;

	/*
	 * blocked:被阻塞的信号的掩码
	 * real_blocked:被阻塞信号的临时掩码(由rt_sigtimedwait系统调用使用)
	 */
	sigset_t blocked, real_blocked;
	/*
	 * 存放私有挂起信号的数据结构
	 */
	struct sigpending pending;

	/*
	 * 信号处理程序备用堆栈的地址
	 */
	unsigned long sas_ss_sp;
	/*
	 * 信号处理程序备用堆栈的大小
	 */
	size_t sas_ss_size;
	/*
	 * 指向一个函数的指针,设备驱动程序使用这个函数阻塞进程的某些信号
	 */
	int (*notifier)(void *priv);
	/*
	 * 指向notifier函数可能使用的数据
	 */
	void *notifier_data;
	sigset_t *notifier_mask;
	
	void *security;
	struct audit_context *audit_context;

/* Thread group tracking */
   	u32 parent_exec_id;
   	u32 self_exec_id;
/* Protection of (de-)allocation: mm, files, fs, tty, keyrings */
	spinlock_t alloc_lock;
/* Protection of proc_dentry: nesting proc_lock, dcache_lock, write_lock_irq(&tasklist_lock); */
	spinlock_t proc_lock;
/* context-switch lock */
	spinlock_t switch_lock;

/* journalling filesystem info */
	/*
	 * 当前活动日志操作处理的地址。
	 * 正在使用的原子操作对象。
	 */
	void *journal_info;

/* VM state */
	struct reclaim_state *reclaim_state;

	struct dentry *proc_dentry;
	struct backing_dev_info *backing_dev_info;

	struct io_context *io_context;

	unsigned long ptrace_message;
	siginfo_t *last_siginfo; /* For ptrace use.  */
/*
 * current io wait handle: wait queue entry to use for io waits
 * If this thread is processing aio, this points at the waitqueue
 * inside the currently handled kiocb. It may be NULL (i.e. default
 * to a stack based synchronous wait) if its doing sync IO.
 */
	wait_queue_t *io_wait;
/* i/o counters(bytes read/written, #syscalls */
	u64 rchar, wchar, syscr, syscw;
#if defined(CONFIG_BSD_PROCESS_ACCT)
	u64 acct_rss_mem1;	/* accumulated rss usage */
	u64 acct_vm_mem1;	/* accumulated virtual memory usage */
	clock_t acct_stimexpd;	/* clock_t-converted stime since last update */
#endif
#ifdef CONFIG_NUMA
  	struct mempolicy *mempolicy;
	short il_next;
#endif
};

二、关于进程的一些基本操作

2.1、查看进程

查看进程有很多种方式,我们今天主要看两种。
第一种:使用ps axj配合grep和管道来查看指定进程。
比如我们现在有一段这样的C程序:

#include <stdio.h>
#include <unistd.h>
 
int main() {                                                                                                                                                                                                 
   while (1) {
     printf("我是一个进程,我正在努力的跑!!\n");
     sleep(1);
   }
   return 0;
}

我们知道当它在内存中运行的时候,就变成了一个进程,所以我们先让它一直运行着:
在这里插入图片描述
然后我们可以再复制一个SSH渠道去监视它:
在这里插入图片描述
第二种方法:在 “/proc” 系统文件夹中查看所有进程:
在这里插入图片描述
但是这里所显示的进程都是以进程的id命名的,所以我们可以先查出进程的id再去寻找:
在这里插入图片描述
其中加上head -1这个指令表示的是显示第一行的信息,即头部信息。

2.2、杀进程

向上述一样,我们启动了一个死循环的进程,他一直在命令行中打印内容。那我们怎么技术它呢?
第一个方法就是在命令行中按下ctrl + c组合键:
在这里插入图片描述
还有一种方法就是在另一个终端中,使用kill命令指定-9选项再加上进程id来结束:
在这里插入图片描述

2.3、获取进程id

我们刚才一直提到进程的id,那它有什么用呢?我们是否可以在代码中获取到对应进程的id呢?
关于进程的id(pid)有什么用我们下面再介绍,我们先来介绍怎样在进程中获取对应进程的pid。
我们可以使用操作系统为我们提供的系统调用 getpid()和getppid() 来获取进程及其父进程的id:
在这里插入图片描述
关于getpidd()和getppid()的返回值,它其实是一个,名为pid_t的类型。我们平时使用仅需要将他看成是int类型即可,打印时也可以使用%d.

2.4、创建进程

我们可以使用系统调用接口fork()创建子进程:
在这里插入图片描述
大家可能看到这样的结果会感到疑惑,为什么子进程的代码会执行了两次,而且看pid会发现有一次还是父进程执行的。
其实fork这样使用是不对的,想要正确的使用我们得先看看fork的使用手册:
在这里插入图片描述
这个接口
“有两个返回值”
,如果创建成功那子进程的pid将返回给父进程,0将返回给子进程,如果创建失败则返回-1。
至于为什么一个函数会有两个返回值,这是一个非常复杂的问题,这需要我们以后再洗洗探讨,我们现在先知道有这么个现象即可。
而fork正确的使用方法是通过fork的返回值对父子进程进行“分流”,即父子进程执行不同的代码。
很简单,我们可以通过判断getpid的返回值来完成:
在这里插入图片描述
从结果可以看出,进程不仅仅行了分流,而且默认是父进程先执行。

三、进程状态

我们知道操作系统对进程的管理本质上就是对进程控制块PCB的管理,而进程状态其实就是PCB内部的一个整型变量,根据不同的整型值来标识进程不同的状态。

3.1、普适操作系统中的进程状态

在很多将操作系统的书上都是将进程的状态分为如下几种:运行、挂起、阻塞、新建、就绪、等待、挂机、死亡。
在这里插入图片描述
而各种教材上面的各种状态的对应的名称也可能不一样,但是他们想要表达的意思是一样的。
其实只要是操作系统,他们的内核都大差不差,只是有些细微的地方不一样而已。

3.2、具体到Linux操作系统中的进程状态

而具体到Linux操作系统,进程的主要状态有以下六种:

R运行状态(running): 并不意味着进程一定在运行中,它表明进程要么是在运行中要么在运行队列里。
S睡眠状态(sleeping): 意味着进程在等待事件完成(这里的睡眠有时候也叫做可中断睡眠(interruptible sleep))。
D磁盘休眠状态(Disk sleep): 有时候也叫不可中断睡眠状态(uninterruptible sleep),在这个状态的进程通常会等待IO的结束。
T停止状态(stopped): 可以通过发送 SIGSTOP 信号给进程来停止(T)进程。这个被暂停的进程可以通过发送 SIGCONT 信号让进程继续运行。
X死亡状态(dead): 这个状态只是一个返回状态,你不会在任务列表里看到这个状态。
僵死状态(Zombies): 是一个比较特殊的状态。当进程退出并且父进程(使用wait()系统调用,后面讲)没有读取到子进程退出的返回代码时就会产生僵死(尸)进程
僵死进程会以终止状态保持在进程表中,并且会一直在等待父进程读取退出状态代码。
所以,只要子进程退出,父进程还在运行,但父进程没有读取子进程状态,子进程进入Z状态

而这些状态,在内核中其实是对应着一个任务状态数组,这实际上是一个字符数组,我们为此可以猜测出,进程的状态其实也是根据这个字符数组中对应的字符来标识的:

/*
* The task state array is a strange "bitmap" of
* reasons to sleep. Thus "running" is zero, and
* you can test for combinations of others with
* simple bit tests.
*/
static const char * const task_state_array[] = {
"R (running)", /* 0 */
"S (sleeping)", /* 1 */
"D (disk sleep)", /* 2 */
"T (stopped)", /* 4 */
"t (tracing stop)", /* 8 */
"X (dead)", /* 16 */
"Z (zombie)", /* 32 */
};

运行状态:
运行状态其实很好理解,只要一个进程正在运行(即进程的PCB位于CPU的运行队列中):
在这里插入图片描述
因为进程一直对a进行+1操作,所以它一直会处于运行状态。
注意: 如果你想进行测试,是一个进程一直处于运行状态,注意一定不使用printf()函数(比如死循环打印),因为这涉及到了io资源的申请,会让进程处于另一个状态:睡眠状态,这个下面会详细讲到。
睡眠状态
睡眠状态其实就是普适操作系统中的阻塞状态,因为进程需要等待某种资源:
在这里插入图片描述
但是有的朋友可能会不解了,这里看到的今晨不是一直在运行着吗,为什么就是睡眠状态呢?
这是因为我们cpu的速度是非常快的,我们人是根本感知不到的,printf需要等待显示器的资源,我们人虽然看到的是屏幕上飞速的打印着,但是在cpu看来就是它等待了很久才能打印一次,所以我们的这个进程其实大部分时间都在等待资源,所以也就是睡眠状态。
深度睡眠状态
这个状态就没办法给大家演示了,因为这是个非常危险的状态,只有在内存空间严重不足时才会出现。如果系统出现了深度睡眠状态,那这个系统也即将崩溃了。而我们想演示也是没有办法做到的,因为它只能通过操作系统来到达。

当操作系统出现空间严重不足时,操作系统会将某些进程直接杀掉来保证系统能够正常运行,而有些进程是非常重要的,如果直接杀掉的话就会造成巨大的损失,这时候操作系统就会讲这些非常重要的进程转换到深度睡眠状态,其做法就是将这个进程的数据写入磁盘,所以这个状态也称为磁盘休眠状态。

处于深度睡眠状态的进程既不能被用户杀掉也不能被操作系统杀掉,只能通过断电或者等待进程自己醒来

暂停状态
在进程中有很多的“信号”,使用这些信号也可以将我们的进程设置成指定的状态,我们可以使用kill -l指令来查看系统信号的详细列表:
在这里插入图片描述
我们今天主要看的是19这个信号,它的作用就是将一个进程设置成暂停状态:
在这里插入图片描述
如果我们想让这个进程恢复运行,可以使用-18选项:
在这里插入图片描述
死亡状态
死亡状态代表着一个进程已经完全结束,进程的PCB和代码数据全部被操作系统回收。
僵尸状态
我们的进程是为了帮助我们完成某种任务,而既然是完成任务,那进程在结束钱就应该返回任务执行的结果,供父进程或操作系统读取。

所以一个进程在退出的时候,并不能直接释放全部资源,对于进程的代码和数据,操作系统可以释放,因为该进程已经不会被执行了,但是该进程的PCB应该被保留,因为PCB中存放着该进程的各种状态代码,特别是退出状态码。

而僵尸状态就是进程在退出时等待父进程或操作系统来读取退出状态码,然后释放PCB的一种状态。

四、僵尸进程和孤儿进程

4.1、僵尸进程

上面我们提到一个进程在全部释放之前需要父进程或操作系统来读取进程的退出状态代码,而如果父进程一直读取子进程的退出状态码,那子进程的PCB将一直得不到释放,此时该进程就变成僵尸进程:
在这里插入图片描述
我们设计这样一个程序,让子进程只执行5次,然后让子进程退出,让父进程一直在执行:
在这里插入图片描述

然后我们在查看对应的子进程就会发现子进程已经变成了僵尸进程了:
在这里插入图片描述
这是因为虽然子进程退出了,但是父进程一直在执行,并不能读取子进程的退出码。

4.2、孤儿进程

孤儿进程是指父进程提前退出后,子进程被操作系统领养的一种情况,被操作系统领养的进程就被称为孤儿进程:
我们只需要将之前的代码改成让父进程先退出,然后子进程一直执行就可以模拟出孤儿进程了:
在这里插入图片描述
在这里插入图片描述

五、进程的优先级

进程的优先级与权限不同,权限是限制那些事情能做安歇事情不能做,而优先级则是规定那些事情先做那些事情后做。

因为CPU的资源是有限的,所以肯定不可能让所有进程都同时运行。所以规定哪个进程先运行哪个进程后运行也就变得至关重要了。所以操作系统就要为不同的进程设置不同的优先级。进程的优先级就是一个整型数字,这个数字越大则优先级越低,数字越小则优先级越高。

5.1、查看进程的优先级

我们可以使用ps -la指令来查看系统内的进程优先级:
在这里插入图片描述
其中这个PRI标题就是进程的优先级,它其实就是英文priority的缩写。而Linux中进程的优先级范围为60-99,Linux中默认的进程优先级为80。

5.2、怎样修改进程的优先级

Linux支持动态的优先级调整,单兵不允许我们直接的修改进程的优先级,我们只能通过修改进程PCB中的一个nice值来间接的修改优先级,而这里的NI就是进程对应的nice值:
在这里插入图片描述
进程的优先级的计算方式:

pri(新) = pri(老) + nice

因为nice的默认值为0,所以进程的默认优先级也就为80了,所以我们可以通过修改nice值来达到修改优先级的目的,修改nice值的其中一个方法的步骤为:

输入top --> 输入r --> 输入进程id --> 输入NI值

在这里插入图片描述
而我们若想把优先级调高就需要root权限:
在这里插入图片描述
而既然Linux已经规定了进程的优先级范围是60-99那也就说明了我们并不能随意地修改进程的优先级,间接的也就不能随意的修改nice值。
通过计算我们得出,规定了进程的优先级范围是60-99那nice值的范围也就是[-20 - 19]:
如果我们修改的范围超过了这个区间,那系统就会把nice只修改为边界情况:
在这里插入图片描述
注:公式 “pri(新) = pri(老) + nice” 中的老优先级每一次都是默认优先级80。

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

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

相关文章

创建ABAP数据库表和ABAP字典对象-使用基本类型增加账号字段03

新增字段 现在你将增加字段&#xff1a;account_number,基于基本类型 1.输入以下内容(包括句点)&#xff0c;然后选择“代码补全”(Ctrl空格): key account_number : abap.2.从下拉列表中选择numc(len)并指定len为8。另外&#xff0c;指定这个关键字段为not null: key accoun…

深入浅出理解深度可分离卷积(Depthwise Separable Convolution)

一、参考资料 详细且通俗讲解轻量级神经网络——MobileNets【V1、V2、V3】 详细且通俗讲解轻量级神经网络——MobileNets【V1、V2、V3】 卷积神经网络中的Separable Convolution 深度学习中常用的几种卷积&#xff08;下篇&#xff09;&#xff1a;膨胀卷积、可分离卷积&#…

postgresql 触发器如何生成递增序列号,从1开始,并且每天重置

大家好&#xff0c;我是三叔&#xff0c;许久不见&#xff0c;这期给大家介绍一下笔者在开发中遇到的业务处理&#xff1a;pgsql 创建触发器生成每日递增序列&#xff0c;并且第二天重置&#xff0c;根据不同的用户进行不同的控制。 1.创建生成递增序列的 table 表 -- 创建us…

新手必看的Facebook广告投放基础思路

一、广告账号要求 如果您还没有Facebook账号&#xff0c;那么第一步是准备Facebook账号。 1、配置正确的网络环境 Facebook账号需要在稳定安全的网络环境中运行&#xff0c;否则很容易导致封禁。像我们常用的是Maskfog指纹浏览器&#xff0c;可以通过自定义浏览器指纹与为环…

计算机网络第4章-网络层(1)

引子 网络层能够被分解为两个相互作用的部分&#xff1a; 数据平面和控制平面。 网络层概述 路由器具有截断的协议栈&#xff0c;即没有网络层以上的部分。 如下图所示&#xff0c;是一个简单网络&#xff1a; 转发和路由选择&#xff1a;数据平面和控制平面 网络层的作用…

Plist编辑软件 PlistEdit Pro mac中文版功能介绍

PlistEdit Pro mac是一款功能强大的Plist文件编辑软件。Plist文件是苹果公司开发的一种XML文件格式&#xff0c;用于存储应用程序的配置信息和数据。PlistEdit Pro可以帮助用户轻松地编辑和管理Plist文件。 PlistEdit Pro具有直观的用户界面和丰富的功能。用户可以使用该软件打…

【计算机网络】网络层——IP

目录 1.概念2.协议格式3.网络划分ip组成IP地址分类IP地址数量私网IP和公网IP子网掩码路由 1.概念 引入 应用层http协议是进行构建和解析请求request和响应response。 传输层的TCP/UDP协议是不提供数据的运输。传输层是为数据传输指定规则。但是&#xff0c;UDP协议并不保证数…

Java八大排序——归并排序

1.什么是归并排序 归并排序是一种基于分治思想的排序算法&#xff0c;它将待排序的序列分成若干个子序列&#xff0c;每个子序列都是有序的&#xff0c;然后再将这些有序的子序列合并成一个有序的序列。归并排序的时间复杂度为O(nlogn)&#xff0c;是一种稳定的排序算法。除了排…

数据分析和用户个性化体验:开发同城外卖APP的技术解决方案

在数字化时代&#xff0c;外卖服务已经成为人们日常生活中不可或缺的一部分。无论是忙碌的白领、学生&#xff0c;还是家庭主妇&#xff0c;都倚赖同城外卖APP来方便地满足他们的饥饿需求。然而&#xff0c;随着竞争的激烈&#xff0c;外卖APP必须不断改进&#xff0c;以满足用…

ajax调用springboot后台接口

工具 api测试工具 由于后台接口不是同一个团队编写的&#xff0c;在文档缺失的情况下&#xff0c;需要测试后台接口接收参数类型&#xff0c;可以使用这个工具&#xff0c;注册很方便 页面如下所示&#xff0c;可以选择请求方法是get&#xff0c;或者post 重点介绍两种&…

SpireCV如何利用TensorRT加速?

TensorRT简介 TensorRT是NVIDIA推出的一款高性能的深度学习推理引擎(C库)。相比于一般的深度学习框架&#xff0c;在GPU模式下其可提供36X的加速&#xff0c;极大提高了深度学习模型在边缘设备上的推断速度&#xff0c;以满足无人机、无人车等无人系统的快速视觉检测场景。 Te…

Google play开发者账号隔离用指纹浏览器还是vps?哪个防关联效果更佳?

很多谷歌安卓开发者会通过矩阵、马甲包的方式&#xff0c;在Google play应用商店上获得更多的流量和收益&#xff0c;这需要多个开发者账号&#xff0c;因此开发者账号隔离问题的重要性不言而喻。 在Google play开发者账号的隔离防关联问题上&#xff0c;使用vps和指纹浏览器是…

Oracle(12)Managing Indexes

目录 目标&#xff1a; 一、基础知识 1、Classification ofindexes 索引的分类 2、B-Tree vs Bitmap 3、Creating Indexes: Guidelines 创建索引:准则 4、Offline Index Rebuild 脱机索引重建 5、RebuildingIndexes 重建索引 6、Online Index Rebuild 在线索引重建 7…

记一次某学院的未授权渗透过程

文章现写的&#xff0c;部分内容有些着急。 0x01 测试过程 开局登录框&#xff0c;没有测试SQL注入与XSS(菜鸟&#xff0c;测也测不出来。) 有system用户&#xff0c;尝试弱口令&#xff0c;无果&#xff01; 直接namp来一下子端口探测吧 发现有3306与8888 3306 mysql测试…

《Generic Dynamic Graph Convolutional Network for traffic flow forecasting》阅读笔记

论文标题 《Generic Dynamic Graph Convolutional Network for traffic flow forecasting》 干什么活&#xff1a;交通流预测&#xff08;traffic flow forecasting &#xff09;方法&#xff1a;动态图卷积网络&#xff08;Dynamic Graph Convolutional Network&#xff09;…

【沧元图】梅元知命运逆转,但遗憾下线,孟川新形态揭晓

Hello,小伙伴们&#xff0c;我是小郑继续为大家深度解析国漫资讯。 深度爆料&#xff0c;《沧元图》是近年来备受期待的动画作品之一&#xff0c;其独特的画风和精彩的剧情吸引了众多观众的关注。这部动画的播出计划备受瞩目&#xff0c;据主创团队透露&#xff0c;本季共有26…

关于GPT的一些使用场景

与传统的机器翻译或语音识别技术不同&#xff0c;GPT强调的是生成新文本的能力&#xff0c;这使得它在创作、摘要、问答等场景下具有独特的优势。下面是我日常生活中用到GPT的一些场景&#xff1a; 日常闲聊 在日常闲聊中&#xff08;尤其是和运营xjj聊天的时候&#xff09;&a…

伊朗网络间谍组织针对中东金融和政府部门

导语 近日&#xff0c;以色列网络安全公司Check Point与Sygnia发现了一起针对中东金融、政府、军事和电信部门的网络间谍活动。这一活动由伊朗国家情报和安全部门&#xff08;MOIS&#xff09;支持的威胁行为者发起&#xff0c;被称为"Scarred Manticore"。该组织被认…

【EI会议征稿】第四届机械、电子电气与自动化控制国际学术会议(METMS 2024)

第四届机械、电子电气与自动化控制国际学术会议&#xff08;METMS 2024&#xff09; 2024 4th International Conference on Mechanical, Electronics and Electrical and Automation Control 2024年第四届机械、电子电气与自动化控制国际学术会议&#xff08;METMS 2024&am…

每日一练 | 网络工程师软考真题Day47

阅读以下关于Linux文件系统和Samba效劳的说明&#xff0c;答复以下【问题1】至【问题3】。 【说明】 Linux系统采用了树型多级目录来管理文件&#xff0c;树型结构的最上层是根目录&#xff0c;其他的所有目录都是从根目录生成的。通过Samba可以实现基于Linux操作系统的效劳器和…