Linux 系统综述
Linux 系统综述
安装与管理
在 Linux 上面,没有双击安装这一说,因此想要安装,我们还得需要命令。CentOS 下面使用 rpm -i jdk-XXX_linux-x64_bin.rpm
进行安装,Ubuntu 下面使用 dpkg -i jdk-XXX_linux-x64_bin.deb
。其中 -i
就是 install 的意思。
主要记 CentOs 的指令。
在 Linux 下面,凭借 rpm -qa
和 dpkg -l
就可以查看安装的软件列表,-q
就是 query,a
就是 all,-l
的意思就是 list。
跟上
grep
更好用,如果单纯要查看,最好用more
或less
跟一下。前者只能向后翻页,后者更加强大。
如果要删除,可以用 rpm -e
和 dpkg -r
。-e
就是 erase,-r
就是 remove。
上面这些都是有『安装包』的情况下的操作,如何在没有安装包的情况下安装呢?CentOS 下面是 yum
,Ubuntu 下面是 apt-get
。例如搜索 jdk 、yum search jdk
和 apt-cache search jdk
,可以搜索出很多很多可以安装的 jdk 版本。
选中一个之后,我们就可以进行安装了。你可以用
yum install java-11-openjdk.x86_64
和apt-get install openjdk-9-jdk
来进行安装。安装以后,如何卸载呢?我们可以使用
yum erase java-11-openjdk.x86_64
和apt-get purge openjdk-9-jdk
。
对于 CentOs 来说,配置文件在 /etc/yum.repos.d/CentOS-Base.repo
里,在这里可以进行 yum 换源等操作。
其实无论是先下载再安装,还是通过软件管家进行安装,都是下载一些文件,然后将这些文件放在某个路径下,然后在相应的配置文件中配置一下。
运行与关闭
配置环境变量和 MacOs 一样,就不记录了。
后台运行使用 nohup
命令,就是 no hang up(不挂起)的意思,最后加一个 &
,就表示后台运行。最终命令的一般形式为 nohup command >out.file 2>&1 &
。这里面,“1”表示文件描述符 1,表示标准输出,“2”表示文件描述符 2,意思是标准错误输出,“2>&1”表示标准输出和错误输出合并了。合并到哪里去呢?到 out.file 里。
关闭指定进程:ps -ef |grep 关键字 |awk '{print $2}'|xargs kill -9
。
ps -ef
可以单独执行,列出所有正在运行的程序;
awk '{print $2}'
是指第二列的内容,是运行的程序 ID ;可以通过
xargs
传递给kill -9
,也就是发给这个运行的程序一个信号,让它关闭。
Linux 也有相应的服务,这就是程序运行的第三种方式,以服务的方式运行。比如 MySQL ,安装完成以后通过命令 systemctl start mysql
启动 MySQL,通过 systemctl enable mysql
设置开机启动。之所以成为服务并且能够开机启动,是因为在 /lib/systemd/system
目录下会创建一个 XXX.service
的配置文件,里面定义了如何启动、如何关闭。
分支进程
在 Linux 里,要创建一个新的进程,需要一个老的进程调用 fork
来实现,其中老的进程叫作父进程(Parent Process),新的进程叫作子进程(Child Process)。对于 fork
系统调用的返回值,如果当前进程是子进程,就返回 0;如果当前进程是父进程,就返回子进程的进程号。对于子进程进行 execve
执行另外的操作,就形成了分支。
有个系统调用
waitpid
,父进程可以调用它,将子进程的进程号作为参数传给它,这样父进程就知道子进程运行完了没有,成功与否。
内存分配
系统分配内存时,当分配的内存数量比较小的时候,使用 brk
,会和原来的堆的数据连在一起,这就像多分配两三个工位,在原来的区域旁边搬两把椅子就行了;当分配的内存数量比较大的时候,使用 mmap
,会重新划分一块区域,也就是说,当办公空间需要太多的时候,索性来个一整块。
Linux 里有一个特点,那就是一切皆文件。每个文件,Linux 都会分配一个文件描述符(File Descriptor),这是一个整数。有了这个文件描述符,我们就可以使用系统调用,查看或者干预进程运行的方方面面。
信号与异常
对于一些不严重的信号,可以忽略,该干啥干啥,但是像 SIGKILL
(用于终止一个进程的信号)和 SIGSTOP
(用于中止一个进程的信号)是不能忽略的,可以执行对于该信号的默认动作。每种信号都定义了默认的动作,例如硬件故障,默认终止;也可以提供信号处理函数,可以通过 sigaction
系统调用,注册一个信号处理函数。
进程间通信
首先就是发个消息,不需要一段很长的数据,这种方式称为消息队列(Message Queue)。由于一个公司内的多个项目组沟通时,这个消息队列是在内核里的,我们可以通过 msgget
创建一个新的队列,msgsnd
将消息发送到消息队列,而消息接收方可以使用 msgrcv
从队列中取消息。
当消息内容较大,可以用内存共享,这时候,我们可以通过 shmget
创建一个共享内存块,通过 shmat
将共享内存映射到自己的内存空间,然后就可以读写了。共用内存可能存在竞争,这就是信号量的机制 Semaphore。
对于只允许一个人访问的需求,我们可以将信号量设为 1。当一个人要访问的时候,先调用
sem_wait
。如果这时候没有人访问,则占用这个信号量,他就可以开始访问了。如果这个时候另一个人要访问,也会调用
sem_wait
。由于前一个人已经在访问了,所以后面这个人就必须等待上一个人访问完之后才能访问。当上一个人访问完毕后,会调用sem_post
将信号量释放,于是下一个人等待结束,可以访问这个资源了。
Glib 与中介
Glibc 是 Linux 下使用的开源的标准 C 库,它是 GNU 发布的 libc 库。Glibc 为程序员提供丰富的 API,除了例如字符串处理、数学运算等用户态服务之外,最重要的是封装了操作系统提供的系统服务,即系统调用的封装。
每个特定的系统调用对应了至少一个 Glibc 封装的库函数,比如说,系统提供的打开文件系统调用 sys_open
对应的是 Glibc 中的 open
函数。
有时候,Glibc 一个单独的 API 可能调用多个系统调用,比如说,Glibc 提供的 printf
函数就会调用如 sys_open
、sys_mmap
、sys_write
、sys_close
等等系统调用。
也有时候,多个 API 也可能只对应同一个系统调用,如 Glibc 下实现的 malloc
、calloc
、free
等函数用来分配和释放内存,都利用了内核的 sys_brk
的系统调用。