Linux开发_Linux下进程编程
任务 1: 进程编程
1.1 进程概念
./a.out //没有运行之前就是静态程序,运行之后就是一个进程
怎么区分进程?能够独立运行的程序,main。
每个进程都有自己唯一的PID号。
命令行可以通过ps命令获取后台进程的PID号。
1. 示例:ps -e 查看后台全部进程
#include <sys/types.h> #include <unistd.h> pid_t getpid(void); //获取进程PID pid_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); //2 signal(SIGIO,sighandler); //29 signal(SIGSYS,sighandler); //31 while(1) { sleep(5); } return 0; } |
Linux系统和windows这些系统属于非实时系统。 ucos\uclinux系统属于实时系统 |
josb查看后台运行的程序作业代号。
fg 1 将后台作业代号为1的程序切换到前台运行
当程序在前台运行时,按下 ctrl+z 可以将程序放入后台,并且暂停运行。
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); //强制终止进程,销毁缓冲区中的数据 } |
查看僵尸进程:ps -aux
查看系统的环境变量: env
修改控制台终端的环境变量: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;
}
2. 练习命名管道的通信,删除指定目录下的指定后缀的文件。
要求:子进程负责遍历文件,父进程就负责删除文件。
dup2(fd_pipe[1],1); //将子进程的标准输出重定向到管道的写端
3. (扩展) 通过命名管道实现本地聊天室,一个终端界面表示一个用户。
注明: 就一个.c程序,运行一个就是一个新的用户,每个进程之间通过命名管道通信。
(1) 每次运行程序需要输入用户名创建用户名。
(2) 每个新加入一个用户有欢迎提示,例如: 欢迎xxx加入xxx聊天室。
(3) 可以互相发送内容,发送内容时的格式: <用户名>: <实际内容>:<发送的时间>
(4) 可以显示在线人数。
(5) 一个用户发送内容,所有的用户都可以显示出来。
(6) 通过一个文件保存聊天记录。
- 点赞
- 收藏
- 关注作者
评论(0)