操作系统第一次上机教程——Linux基础

@(学习资料)[OS, shell 命令,C 语言,GCC编译]

认识Linux

  • 岳友(yoyo9170@163.com)

关于Linux的历史

也许有人已经了解到,Linux 和 Unix 是非常像的。没错,Linux 就是根据 Unix 演变过来的。 当年 Linus Torvalds 就是因为接触到了 Unix 而后才自己想开发一个简易的系统内核的,他开发 的简易系统内核其实就是 Linux。当时 Linus 把开发的这个系统内核丢到网上提供大家下载,由于 它的精致小巧,越来越多的爱好者去研究它。人们对这个内核添枝加叶,而后成为了一个系统。 也许你听说过吧,Linux 是免费的。其实这里的免费只是说 Linux 的内核免费。在 Linux 内核的 基础上而产生了众多 Linux 的版本。
Linux 的发行版说简单点就是将 Linux 内核与应用软件做一个打包。较知名的发行版有: Ubuntu、RedHat、CentOS、Debain、Fedora、SuSE、OpenSUSE、TurboLinux、 BluePoint、RedFlag、Xterm、SlackWare 等。
而常用的就是 Redhat 和CentOS,这里有必要说一下,其实 CentOS 是基于 Redhat 的, 网上有人说,Centos 是 Redhat 企业版的克隆。CentOS 较之于 Redhat 可以免费使用 yum 下载安装所需要的软件包,这个是相当方便的。而 Redhat 要想使用 yum 必须要购买服务了。

图形界面还是命令窗口

对于 linux 的应用,我想大多数都是用在服务器领域,对于服务器来讲真的没有必要跑一个图形界 面。所以我们平时安装 linux 操作系统时往往是不安装图形界面的。说到这里也许你会有疑问,图 形界面还能选择装或者不装?
是的,虽然 linux 和微软的 windows 一样同位操作系统,但是它们有一个很大的区别就是 windows 操作系统的图形界面是和内核一体的,俗称微内核,而 linux 操作系统图形界面就像一个软件一样, 和内核并不是一体的。所以 linux 你可以选择不安装图形界面,这样不仅不影响服务器的正常使用 还可以节省系统资源的开销,何乐而不为呢?
如果你对 linux 超级感兴趣,想使用 linux 就像使用 windows 一样,那你可以安装图形界面,可以像 windows 一样来体验 linux 也是蛮不错的。但是如果你想成为一个专业的 linux系统工程师,那我建 议你从第一天开始就不要去安装图形界面,从命令窗口开始熟悉它。
另外一点值得说的是,日常应用中,我们都是远程管理服务器的,不可能开着图形界面来让你去操作, 虽然目前也有相应的工具支持远程图形连接服务器,可是那样太消耗网络带宽资源,所以从这方面 来考虑还是建议你不要使用图形界面。

Linux基础操作命令

强烈建议大家可以去阅读《鸟哥的私房菜》,这是对于Linux初学者来说就是圣典。

1、查看登录用户

1
2
$ who
$ who am i

2、查看虚拟控制台(终端)当前目录

1
$ pwd

3、查看联机(帮助)手册

1
$ man cd   #查看 cd 命令的帮助文档(按 HJKL 移动光标,按 Q 退出)

4、查看当前工作目录下的文件

  • 常见用法

    1
    2
    buaasoft@buaasoft_virtual_machine:/var$ ls
    backups cache crash games lib local lock log mail opt run spool tmp
  • 查看全部文件

    1
    2
    buaasoft@buaasoft_virtual_machine:/var$ ls -a
    . .. backups cache crash games lib local lock log mail opt run spool tmp
  • 查看详细信息

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    buaasoft@buaasoft_virtual_machine:/var$ ls -l
    total 44
    drwxr-xr-x 2 root root 4096 Aug 16 03:48 backups
    drwxr-xr-x 17 root root 4096 Oct 13 20:40 cache
    drwxrwsrwt 2 root whoopsie 4096 Nov 21 00:44 crash
    drwxr-xr-x 2 root root 4096 Mar 27 2012 games
    drwxr-xr-x 61 root root 4096 Nov 21 00:48 lib
    drwxrwsr-x 2 root staff 4096 Jan 27 2012 local
    lrwxrwxrwx 1 root root 9 Aug 16 03:28 lock -> /run/lock
    drwxr-xr-x 18 root root 4096 Nov 21 00:48 log
    drwxrwsr-x 2 root mail 4096 Mar 27 2012 mail
    drwxr-xr-x 2 root root 4096 Mar 27 2012 opt
    lrwxrwxrwx 1 root root 4 Aug 16 03:28 run -> /run
    drwxr-xr-x 8 root root 4096 Mar 27 2012 spool
    drwxrwxrwt 2 root root 4096 Aug 15 20:13 tmp
  • 查看隐藏文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    buaasoft@buaasoft_virtual_machine:/var$ ls -la #或者 ls -al, ls -l -a
    total 52
    drwxr-xr-x 13 root root 4096 Aug 16 03:28 .
    drwxr-xr-x 23 root root 4096 Aug 4 00:20 ..
    drwxr-xr-x 2 root root 4096 Aug 16 03:48 backups
    drwxr-xr-x 17 root root 4096 Oct 13 20:40 cache
    drwxrwsrwt 2 root whoopsie 4096 Nov 21 00:44 crash
    drwxr-xr-x 2 root root 4096 Mar 27 2012 games
    drwxr-xr-x 61 root root 4096 Nov 21 00:48 lib
    drwxrwsr-x 2 root staff 4096 Jan 27 2012 local
    lrwxrwxrwx 1 root root 9 Aug 16 03:28 lock -> /run/lock
    drwxr-xr-x 18 root root 4096 Nov 21 00:48 log
    drwxrwsr-x 2 root mail 4096 Mar 27 2012 mail
    drwxr-xr-x 2 root root 4096 Mar 27 2012 opt
    lrwxrwxrwx 1 root root 4 Aug 16 03:28 run -> /run
    drwxr-xr-x 8 root root 4096 Mar 27 2012 spool
    drwxrwxrwt 2 root root 4096 Aug 15 20:13 tmp

在 Ubuntu 上,还可以使用llla

5、切换工作目录

1
2
3
4
5
$ cd /usr	# 进入绝对路径 '/usr'
$ cd .. # 返回上一层目录
$ cd - # 回到刚才目录
$ cd / # 进入根目录
$ cd ~ # 进入用户目录

6、创建目录和文件

1
2
3
$ mkdir lab		# 在当前目录下创建 lab 目录
$ mkdir -p lab/report # 在当前目录下创建 lab ,并在 lab 下创建 report
$ touch hello.c # 创建一个名为 hello.c 的空文件

7、删除目录和文件

1
2
3
4
$ rm hello.c 	# 删除文件hello.c
$ rmdir lab # 删除空目录lab
$ rm -r lab # 删除空目录lab
$ rm -rf lab # 删除目录lab(可以非空)

8、复制和移动文件

1
2
$ cp source target # 将 source 复制到 target (保留原文件)
$ mv source target # 将 source 移动到 target (不保留原文件)

Linux C编程基础

1、GCC的使用

  • vim 编写hello.c源文件
    1
    2
    3
    4
    5
    6
    #include <stdio.h>

    int main(int argc, char *argv[], char *env[]){
    printf("%s\n","hello,world!");
    return 0;
    }

思考一下main函数第三个参数的作用!

  • 使用GCC编译源代码
    1
    2
    3
    4
    5
    $ gcc -E hello.c -o hello.i 	# 预处理,生成hello.i
    $ gcc -S hello.c -o hello.s # 编译,生成汇编文件 hello.s
    $ gcc -c hello.c -o hello.o # 编译,生成目标代码 hello.o
    $ gcc hello.o -o hello # 链接,生成可执行文件 hello
    $ ./hello # 执行 hello

当然上面是为了让大家了解C代码是如何被编译、链接并最终执行的过程,其中每一步过程对于开发者来说都是透明的,如果熟悉了这一系列的步骤,可以采取gcc hello.c -o hello 一步生成可执行文件。

2、GCC编译多源码文件的工程

myprintf.h文件

1
2
3
4
5
6
#ifndef MYPRINTF_H
#define MYPRINTF_H

void myprintf(char *);

#endif

myprintf.c文件

1
2
3
4
5
6
#include <stdio.h>
#include "myprintf.h"

void myprintf(char *s){
printf("myprintf: %s.\n",s);
}

main.c文件

1
2
3
4
5
6
#include "myprintf.h"

int main(void){
myprintf("hello,world!");
return 0;
}

思考一下ifndefdefineendif三者的作用,为什么这样组织文件?

  • 使用GCC 编译
    1
    2
    3
    4
    $ gcc -c myprintf.c -o myprintf.o
    $ gcc -c main.c -o main.o
    $ gcc myprintf.o main.o -o hello
    $ ./hello # 执行

思考为什么需要多步编译,能不能一步编译成功?

Makefile 入门

上面最后的问题,答案是肯定的。用Makefile编译上面的三个文件,创建一个名为Makefile的文件,内容如下:

1
2
3
4
5
6
7
8
hello: myprintf.o main.o
gcc -o hello myprintf.o main.o

myprintf.o: myprintf.c myprintf.h
gcc -c -o myprintf.o myprintf.c

main.o: main.c myprintf.h
gcc -c -o main.o main.c

然后在命令行下执行make命令,就可以得到hello文件。
Makefile 文件的核心组成是“规则”,一条规则的结构如下:

1
2
3
4
目标:条件 1 条件 2 ...
命令 1
命令 2
...

注意,各条命令前面必须有一个Tab(制表符),不能是两个Tab,也不能是空格,只能是一个Tab
概括起来相当于:要得到“目标”,需要具备“条件1”、“条件2”……,并且要顺序地执行“命令 1”、“命令2”……
条件可以是文件,也可以是其他规则的目标。执行make命令的时候,make会在当前目录下寻找Makefile问价,并将文件的第一条规则的目标当做本次执行的目标。
Makefile的功能非常复杂,可以用一整本书来讲,下面只介绍一些基本用法。
Makefile可以定义变量, :=用来赋值,使用变量的时候要用$(..)。前面的例子可以改写 为:

1
2
3
4
5
6
7
8
9
10
11
TARGET := hello
CC := gcc

$(TARGET): myprintf.o main.o
$(cc) -o hello myprintf.o main.o

myprintf.o: myprintf.c myprintf.h
$(cc) -c -o myprintf.o myprintf.c

main.o: main.c myprintf.h
$(cc) -c -o main.o main.c

在每一条规则内部,可以使用$@来代表这条规则的目标,用$<来表示这条规则中的第一个条件,用$^表示所有的条件,因此前面的例子可以改写为:

1
2
3
4
5
6
7
8
9
10
11
TARGET := hello
CC := gcc

$(TARGET): myprintf.o main.o
$(cc) -o $@ @^

myprintf.o: myprintf.c myprintf.h
$(cc) -c -o $@ $<

main.o: main.c myprintf.h
$(cc) -c -o $@ $<

如果不想在执行make命令的时候看到一对命令的输出,可以在命令前面加上 @ ,例如:

1
2
3
4
5
6
7
8
9
10
11
TARGET := hello
CC := gcc

$(TARGET): myprintf.o main.o
$(cc) -o $$^

myprintf.o: myprintf.c myprintf.h
$(cc) -c -o $$<

main.o: main.c myprintf.h
$(cc) -c -o $$<

如果还想看到编译的过程,可以加入一些自定义的输出命令,打印一些内容到终端:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
TARGET := hello
CC := gcc

$(TARGET): myprintf.o main.o
@echo "\033[1;34mlinking $@\033[0m"
$(cc) -o $$^

myprintf.o: myprintf.c myprintf.h
@echo "\033[1;32mcompiling $@\033[0m"
$(cc) -c -o $$<

main.o: main.c myprintf.h
@echo "\033[1;32mcompiling $@\033[0m"
$(cc) -c -o $$<

echo命令中的\033[1;34m表示切换颜色。
Makefile有一个功能,就是会自动比较目标文件的时间和依赖项的最近更改时间,只有需要重新 编译的文件Makefile才会执行相应的命令。对于一个比较大的项目,这个特点可以节省很多的时 间。
如果希望自动清理编译缓存(就是删除编译过程中生成的.o文件),可以给Makefile 加一个新 的规则:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
TARGET := hello
CC := gcc

$(TARGET): myprintf.o main.o
@echo "\033[1;34mlinking $@\033[0m"
$(cc) -o $$^

myprintf.o: myprintf.c myprintf.h
@echo "\033[1;32mcompiling $@\033[0m"
$(cc) -c -o $$<

main.o: main.c myprintf.h
@echo "\033[1;32mcompiling $@\033[0m"
$(cc) -c -o $$<

clean:
@echo "\033[1;33mcleaning $@\033[0m"
rm *.o