写点什么

Linux 开发 _Linux 下进程编程

作者:DS小龙哥
  • 2022 年 6 月 18 日
  • 本文字数:2937 字

    阅读完需:约 10 分钟

本篇文章主要是介绍 Linux 下进程相关知识点,命令行控制进程的相关命令,介绍创建进程、管理进程相关函数。

任务 1: 进程编程

1.1 进程概念

./a.out //没有运行之前就是静态程序,运行之后就是一个进程


怎么区分进程?能够独立运行的程序,main。


每个进程都有自己唯一的 PID 号。


命令行可以通过 ps 命令获取后台进程的 PID 号。


示例:ps -e 查看后台全部进程


#include <sys/types.h>#include <unistd.h>pid_t getpid(void); //获取进程PIDpid_t getppid(void);
复制代码


C 语言代码方式获取 PID


#include <stdio.h>#include <sys/types.h>#include <unistd.h>int main(int argc,char **argv){pid_t pid=getpid();printf("当前进程PID=%d ",pid);pid=getppid();printf("PPID=%d \n",pid);return 0;}
复制代码

1.2 进程的信号

kill 命令功能:给程序发送信号。


查看所有支持的信号:kill -l



kill [-s signal|-p] [--] pid... kill -l [signal] :查看指定信号的帮助信息


发送信号的方式:


【1】kill <进程 PID> //默认发送的进程终止信号,示例: #kill 348374


【2】kill -s <具体信号> <进程的 PID> 示例: #kill -s SIGINT 7646


【3】kill -<具体信号> <进程的 PID > 示例: # kill -SIGINT 7734


信号的捕获


#include <signal.h>typedef void (*sighandler_t)(int);sighandler_t signal(int signum, sighandler_t han-dler);参数:int signum :要捕获的信号sighandler_t han-dler:函数指针
复制代码


信号的捕获示例


#include <stdio.h>#include <sys/types.h>#include <unistd.h>#include <signal.h>void sighandler(int sig){printf("捕获的信号值=%d\n",sig);}int main(int argc,char **argv){//将指定信号绑定到指定的函数上signal(SIGINT,sighandler); //2signal(SIGIO,sighandler); //29signal(SIGSYS,sighandler); //31while(1){sleep(5);}return 0;}
复制代码


Linux 系统和 windows 这些系统属于非实时系统。 ucos\uclinux 系统属于实时系统


【1】josb 查看后台运行的程序作业代号。


【2】fg 1 将后台作业代号为 1 的程序切换到前台运行


【3】当程序在前台运行时,按下 ctrl+z 可以将程序放入后台,并且暂停运行。


【4】bg 1 将后台暂停的程序切换为运行状态

1.3 进程的创建

#include <stdio.h>#include <sys/types.h>#include <unistd.h>#include <signal.h>int main(int argc,char **argv){pid_t pid;pid=fork(); //创建一个新的进程if(pid==0) //子进程{printf("子进程pid=%d\n",getpid());}else if(pid>0) //父进程{printf("父进程pid=%d\n",getpid());}else //进程创建错误{printf("进程创建失败!\n");}return 0;}
复制代码


fork 函数创建新进程本身属于一个拷贝的过程。继承功能!


进程的退出


#include <stdio.h>#include <sys/types.h>#include <unistd.h>#include <signal.h>#include <stdlib.h>void print(void);int main(int argc,char **argv){print();printf("main函数执行!");return 0;}
void print(void){printf("子函数执行!");//return; //终止函数,会将缓冲区里的数据输出//exit(0); //直接终止进程,会将缓冲区里的数据输出_exit(0); //强制终止进程,销毁缓冲区中的数据}
复制代码


【1】查看僵尸进程:ps -aux


【2】查看系统的环境变量: env


【3】修改控制台终端的环境变量:export PS1='[\u@\h \W \t]$'

1.4 进程的执行

#include <stdlib.h>int system(const char *command); // “ls -l” …..”cd”
复制代码


接收命令的返回值:


#include <stdio.h>int main(int argc,char **argv){system("pwd >123.txt"); //获取脚本或者其他程序的返回值return 0;}
复制代码


可变形参


#include <stdio.h>void func(int data,...);int main(int argc,char **argv){int data=888;func(data,123,456,789,100);return 0;}
void func(int data,...){int i=0;int *p=&data;for(i=0;i<5;i++){printf("%d\n",*p++);}}
复制代码


执行进程


#include <stdio.h>#include <unistd.h>int main(int argc,char **argv){execl("/bin/ls","ls","-l",NULL);printf("123\n");return 0;}
#include <stdio.h>#include <unistd.h>int main(int argc,char **argv){execlp("ls","ls","-l",NULL); //PATH=xxx:xxx:xxx:printf("123\n");return 0;
}
复制代码


管道:FIFO--->先入先出


通过命令行: mkfifo 命令可以直接创建 FIFO 文件。


无名管道的 FIFO 文件不是实体文件,存在内存中的。


文件的方向: 即 fds[0]和读端相对应, fds[1]和写端相对应


有名管道的 FIFO 文件是实体文件,存在硬盘中的。


#include <stdio.h>#include <unistd.h>/*#include <unistd.h>int pipe(int pipefd[2]);*/int main(int argc,char **argv){int pipefd[2];char buff[100];pipe(pipefd); //创建一个无名管道 [0]读 [1]写int pid=fork();if(pid) //父进程{while(1){write(pipefd[1],"12345",6);sleep(1);}}
else //子进程{while(1){read(pipefd[0],buff,100);printf("buff=%s\n",buff);}}return 0;}
复制代码

1.5 练习

【1】练习无名管道的通信,删除指定目录下的指定后缀的文件。


要求:子进程负责遍历文件,父进程就负责删除文件。


#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <string.h>
/*无名管道:fds[0] 表示读 fds[1] 表示写
int dup2(int oldfd, int newfd); //实现文件描述符的重定向示例: dup2(fds[1],1); //将本程序的标准输出定义到管道的写端
标准输入:0标准输出:1标准错误:2*/int main(int argc,char **argv){ if(argc!=2) { printf("参数格式: ./app <传入一个文件>\n"); exit(-1); //退出进程 } int fds[2]; //定义了管道文件 pipe(fds); //创建无名管道文件 char buff[100]; char cmd[100]; int status; int pid=fork(); int len; if(pid==0) //子进程,遍历目录,查找文件 { write(fds[1],argv[1],strlen(argv[1])); //写入数据 /* 1. 定义一个二维数组,先将所有目录遍历完毕,将得到数据一次性写过去 2. 遍历一个就写一个。(编写一个应答机制) */ } else if(pid>0) //父进程,负责删除文件 { len=read(fds[0],buff,100); buff[len]='\0'; strcpy(cmd,"rm "); strcat(cmd,"-rf "); strcat(cmd,buff); printf("cmd=%s\n",cmd); system(cmd); //执行最终的操作 wait(&status); //随机等待一个子进程退出 } else { printf("进程创建失败!\n"); exit(-1); } return 0;}
复制代码


【3】练习命名管道的通信,删除指定目录下的指定后缀的文件。


要求:子进程负责遍历文件,父进程就负责删除文件。


dup2(fd_pipe[1],1); //将子进程的标准输出重定向到管道的写端


【4】 (扩展) 通过命名管道实现本地聊天室,一个终端界面表示一个用户。


注明: 就一个.c 程序,运行一个就是一个新的用户,每个进程之间通过命名管道通信。


(1) 每次运行程序需要输入用户名创建用户名。


(2) 每个新加入一个用户有欢迎提示,例如: 欢迎 xxx 加入 xxx 聊天室。


(3) 可以互相发送内容,发送内容时的格式: <用户名>: <实际内容>:<发送的时间>


(4) 可以显示在线人数。


(5) 一个用户发送内容,所有的用户都可以显示出来。


(6) 通过一个文件保存聊天记录。

发布于: 刚刚阅读数: 3
用户头像

DS小龙哥

关注

之所以觉得累,是因为说的比做的多。 2022.01.06 加入

熟悉C/C++、51单片机、STM32、Linux应用开发、Linux驱动开发、音视频开发、QT开发. 目前已经完成的项目涉及音视频、物联网、智能家居、工业控制领域

评论

发布
暂无评论
Linux开发_Linux下进程编程_6月月更_DS小龙哥_InfoQ写作社区