1. 介绍
在深入了解Linux系统的运行原理之前,我们先来了解一下Linux中的进程。进程是指在操作系统中运行的一个程序,它是系统进行资源分配和调度的基本单位。每个进程都有自己的虚拟地址空间、代码段、数据段和堆栈等。
2. 查看正在运行的进程
Linux提供了多种方法来查看正在运行的进程,以便我们了解系统的运行情况。
2.1 top命令
top命令是一个基于字符界面的动态进程查看工具,通过该命令可以实时地查看系统中的进程情况。
top
在top输出的结果中,我们可以看到每个进程的PID(进程ID)、USER(进程所属用户)、PR(进程优先级)、NI(优先级调整值)、VIRT(虚拟内存使用量)、RES(物理内存使用量)等信息。
2.2 ps命令
ps命令是一个用于报告当前系统中的进程状态的命令。它可以显示出运行在系统中的进程列表。
ps -ef
ps命令的输出结果中包含有各个进程的PID、PPID(父进程ID)、USER(进程所属用户)、%CPU(CPU使用率)、%MEM(内存使用率)等信息。
3. 进程状态
在Linux系统中,每个进程都有自己的状态。根据进程的状态,我们可以了解到进程当前所处的位置和状态。
3.1 运行状态(R)
运行状态表示进程正在运行或者正在被调度执行。
int main()
{
while(1) {
// 一直执行
}
return 0;
}
在上述代码中,主进程会一直运行,直到用户手动终止。
3.2 睡眠状态(S)
睡眠状态表示进程正在等待某一事件的发生,比如等待用户输入、等待网络数据接收等。
int main()
{
char buf[1024];
fgets(buf, sizeof(buf), stdin);
return 0;
}
在上述代码中,主进程会等待用户输入一行字符串,直到用户按下回车键才会继续执行。
3.3 僵尸状态(Z)
僵尸状态表示进程已经结束执行,但是其父进程还没有对其进行善后处理。
int main()
{
pid_t pid = fork();
if (pid == 0) {
exit(0);
} else {
while(1) {
// 父进程不退出
}
}
return 0;
}
在上述代码中,子进程会立即退出,但是父进程会一直运行。子进程退出后,父进程并没有对其进行回收,导致子进程变成了僵尸进程。
4. 进程间通信
在Linux系统中,进程之间可以通过多种方式进行通信,以便实现数据交换和协作工作。
4.1 管道(Pipe)
管道是一种半双工的通信方式,可以将一个进程的输出连接到另一个进程的输入,实现它们之间的数据传递。
int main()
{
int fd[2];
char buf[1024];
pipe(fd);
if (fork() == 0) {
close(fd[0]);
write(fd[1], "Hello", 5);
exit(0);
} else {
close(fd[1]);
read(fd[0], buf, sizeof(buf));
printf("%s\n", buf);
}
return 0;
}
在上述代码中,通过pipe函数创建了一个管道,然后通过fork函数创建了一个子进程。子进程关闭了管道的读端,向管道中写入了一个字符串,然后退出。父进程关闭了管道的写端,从管道中读取数据,并打印出来。
4.2 共享内存(Shared Memory)
共享内存是指多个进程共享同一块物理内存区域,从而实现数据的共享。进程可以直接读写共享内存中的数据,避免了数据的拷贝开销。
int main()
{
int shmid;
char *shmaddr;
shmid = shmget(IPC_PRIVATE, 1024, IPC_CREAT | 0666);
shmaddr = (char *)shmat(shmid, NULL, 0);
if (fork() == 0) {
strcpy(shmaddr, "Hello");
exit(0);
} else {
wait(NULL);
printf("%s\n", shmaddr);
shmdt(shmaddr);
shmctl(shmid, IPC_RMID, NULL);
}
return 0;
}
在上述代码中,首先通过shmget函数创建了一个共享内存区域,然后通过shmat函数将共享内存附加到当前进程的地址空间中。子进程向共享内存中写入了一个字符串,父进程等待子进程退出后,从共享内存中读取数据,并打印出来。
4.3 消息队列(Message Queue)
消息队列是一个链表,用于存放消息的缓冲区。进程可以通过消息队列向其他进程发送消息,以便进行通信。
int main()
{
int msgid;
struct msgbuf msg;
msgid = msgget(IPC_PRIVATE, IPC_CREAT | 0666);
if (fork() == 0) {
msg.mtype = 1;
strcpy(msg.mtext, "Hello");
msgsnd(msgid, &msg, sizeof(msg.mtext), 0);
exit(0);
} else {
wait(NULL);
msgrcv(msgid, &msg, sizeof(msg.mtext), 1, 0);
printf("%s\n", msg.mtext);
msgctl(msgid, IPC_RMID, NULL);
}
return 0;
}
在上述代码中,首先通过msgget函数创建了一个消息队列,然后通过msgsnd函数向消息队列中发送了一条消息。父进程等待子进程退出后,从消息队列中读取消息,并打印出来。
5. 总结
本文介绍了Linux系统中的进程及其相关内容。我们了解到如何查看正在运行的进程,进程的不同状态以及进程间的通信方式。了解这些内容对于我们深入理解Linux系统的运行原理和开发高效、稳定的应用程序都非常重要。