linux作业

用户和权限管理

创建四个系统用户

为系统添加以下四个用户:

  • alice
  • bob
  • john
  • mike
1
2
3
useradd -d /home/bob -m bob
useradd -d /home/john -m john
useradd -d /home/mike -m mike

为四个用户设置密码

1
2
3
4
passwd alice
passwd bob
passwd john
passwd mike

创建共享目录

/home 目录下创建一个名为 work 的共享目录:

1
mkdir /home/work

创建用户组并添加成员

创建一个名为 workgroup 的用户组:

1
groupadd workgroup

将用户 alice, bob, john 加入该组:

1
2
3
4
usermod -a -G workgroup alice   # 添加为附加组
usermod -g workgroup alice # 设置为 alice 的主组(primary group)
usermod -a -G workgroup bob
usermod -a -G workgroup john
  • 主组(Primary Group):每个用户有且只有一个,是用户创建文件时默认继承的组
  • 附加组(Supplementary Group):用户可以有多个,用于额外获得某些组的权限,但不会影响新建文件的默认组

查看某个组(group)的信息

1
getent group workgroup

修改共享目录的所有权

/home/work 目录的属主改为 alice,属组改为 workgroup

1
chown alice:workgroup /home/work

修改 work 目录的权限

  • 属组内的用户(workgroup 组成员)→ 完全访问权限(rwx)
  • 属组外的用户 → 没有访问权限(—)
1
chmod ug+rwx,o-rwx /home/work
  • ug+rwx:用户(user)和组(group)都加上读、写、执行权限
  • o-rwx:其他人(others)去掉所有权限(读、写、执行)

尝试以 bob 用户身份在 work 目录下创建文件

切换到 bob 用户:

1
su - bob

创建文件:

1
touch /home/work/bob.txt

查看是否成功:

1
ls -l /home/work/bob.txt

尝试以 john 的身份查看或修改 bob.txt

1
2
3
4
su - john
cat /home/work/bob.txt #查看文件内容
echo "hello" >> /home/work/bob.txt
ls -l /home/work/bob.txt #查看权限

尝试以 mike 的身份查看或修改 bob.txt

1
2
3
4
su - mike
cat /home/work/bob.txt
echo "mike tried" >> /home/work/bob.txt
cd /home/work

进程管理与调试

编写 badproc.sh 脚本

Shell 程序(Shell Script) 就是一系列 Shell 命令的集合,写在一个文件里,可以像程序一样自动、批量、重复执行

1
2
3
4
5
6
7
8
#!/bin/bash
while echo "I'm making files!"
do
mkdir adir
cd adir
touch afile
sleep 10s
done

#!/bin/bash → 指定用 bash 解释器执行

while echo "..."无限循环,每次循环前先打印一句话(等价于 while true; do ... done

循环体内:

  • 创建目录 adir
  • 进入该目录
  • 创建文件 afile
  • 睡眠 10 秒 → 避免太快占满磁盘

添加可执行权限

1
2
3
chmod +x badproc.sh
#验证
ls -l badproc.sh

在后台运行脚本

1
./badproc.sh &

查看进程号

1
ps aux | grep badproc

杀死进程

1
kill 12345

删除脚本运行时创建的目录和文件

1
rm -rf adir

创建源文件 fork.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>

int main() {
pid_t pid;

/* fork another process */
pid = fork();
if (pid < 0) { /* error occurred */
fprintf(stderr, "Fork Failed\n");
exit(-1);
}
else if (pid == 0) { /* child process */
printf("This is child process, pid=%d\n", getpid());
execl("/bin/ls", "ls", NULL); // 执行 ls 命令
printf("Child process finished\n"); // 这句不会打印,除非 execl 失败
}
else { /* parent process */
printf("This is parent process, pid=%d\n", getpid());
wait(NULL); // 等待子进程结束
printf("Child Complete\n");
exit(0);
}
}

编译程序(带调试信息)

1
gcc -g -o fork fork.c

先运行一次,看看效果

1
./fork

gdb 调试 fork 程序

1
2
3
4
5
6
gdb ./fork
#在 fork() 调用前设置
(gdb) set follow-fork-mode child
#设置断点和 catch exec
break main
catch exec

Linux编程环境熟悉

C++编译

创建一个名为 helloworld.cpp 的文件,nano helloworld.cpp

1
2
3
4
5
6
7
8
#include <iostream>
using namespace std;

int main(void)
{
cout << "Hello world" << endl;
return 0;
}

Ctrl+O 保存,再按 Ctrl+X 退出 nano

1
2
3
4
#编译程序
g++ -o hello helloworld.cpp
#运行程序
./hello

创建小型函数库

创建源文件 fred.cbill.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/* fred.c */
#include <stdio.h>

void fred(int arg)
{
printf("fred: we passed %d\n", arg);
}

/* bill.c */
#include <stdio.h>

void bill(char *arg)
{
printf("bill: we passed %s\n", arg);
}

编译成目标文件(.o)

1
gcc -c bill.c fred.c

创建头文件 lib.h

1
2
3
/* lib.h */
void bill(char *);
void fred(int);

创建主程序 program.c

1
2
3
4
5
6
7
8
9
/* program.c */
#include <stdlib.h>
#include "lib.h" // 引入我们自己写的头文件

int main()
{
bill("Hello World");
exit(0); // 正常退出
}

编译主程序(只编译,不链接)

1
gcc -c program.c

创建静态库 libfoo.a

使用 ar 命令把 bill.ofred.o 打包成一个静态库:

  • ar:archive 工具,用于创建静态库
  • c:创建新库
  • r:将文件插入到库中(如果不存在则添加)
  • v:显示详细信息
1
ar crv libfoo.a bill.o fred.o

链接主程序和静态库

现在我们要把 program.olibfoo.a 链接起来,生成最终可执行文件 program

1
gcc -o program program.o libfoo.a

运行程序

1
./program