技术笔记!
前言
一、概念
1.程序:存放在磁盘上的指令和数据的有序集合(文件),静态的。
2.进程:执行一个程序所分配的资源的总称;进程是程序的一次执行过程;
动态的,包括创建、调度、执行和消亡;
3.进程和程序内容区别:
BSS段:通常是指用来存放程序中未初始化的全局变量的一块内存区域。BSS是英文Block Started by Symbol的简称。
数据段:通常是指用来存放程序中已初始化的全局变量的一块内存区域。
代码段:通常是指用来存放程序执行代码的一块内存区域。这部分区域的大小在程序运行前就已经确定,在代码段中,也有可能包含一些只读的常数变量,例如字符串常量等。
堆(heap):堆是用于存放进程运行中被动态分配的内存段,当进程调用malloc等函数分配内存时,新分配的内存就被动态添加到堆上(堆被扩张);当利用free等函数释放内存时,被释放的内存从堆中被剔除(堆被缩减)。 栈(stack):栈又称堆栈, 是用户存放程序临时创建的局部变量,(但不包括static声明的变量,static意味着在数据段中存放变量)。除此以外,在函数被调用时,其参数也会被压入发起调用的进程栈中,并且待到调用结束后,函数的返回值也会被存放回栈中。由于栈的先进后出特点,所以栈特别方便用来保存/恢复调用现场。从这个意义上讲,我们可以把堆栈看成一个寄存、交换临时数据的内存区。 4.进程的类型:![](/i/ll/?i=direct/4f49f569c1334729a9ad1d20ff3db291.png)
二、进程
1.查看进程信息
(1)ps 查看系统进程快照
参数:
-e:显示所有进程;
-l:长格式显示更加详细的信息;
-f:全部列出,通常和其他选项;
(2)top 查看进程动态信息
shift + > 后翻页
shift + < 前翻页
top -p PID 查看某个进程
(3)/proc 查看进程详细信息
2.前后台进程切换
(1)jobs 查看后台进程;
(2)bg 将挂起的进程后台运行;
(3)fg 把后台运行的进程放到前台运行
3.改变进程优先级
(1)nice 按用户指定的优先级运行进程
(2)renice 该变正在运行进程的优先级
ctrl + z 把运行的前台进程转为后台并停止。
./test & 把test程序后台运行。
4.进程的创建与结束
(1)子进程:由另外一个进程(对应称之为父进程)所创建的进程。
(2)子进程的创建 fork
函数:
#include <unistd.h>
pid_t fork(void);
返回值:创建新的进程,失败返回-1;成功时父进程返回子进程的进程号,子进程返回0;
通过fork的返回值区分父进程和子进程。
eg:
注意事项:
(1)子进程只执行fork之后的代码;
(2)父子进程执行顺序由操作系统决定的。
子进程继承了父进程的内容;
父子进程有独立的地址空间,互不影响;
若父进程先结束
子进程成为孤儿进程,被init进程收养
子进程变成后台进程
若子进程先结束
父进程如果没有及时回收,子进程变成僵尸进程
(2)进程结束 exit
函数:
#include <stdlib.h>
#include <unistd.h>
void exit(int status);
void _exit(int status);
void _Exit(int status);
结束当前的进程并将status返回
exit结束进程时会刷新(流)缓冲区
eg:
return 和exit的区别
main函数结束时会隐式地调用exit函数,普通函数return是返回上一级。
5.进程回收 wait
(1)wait
#Include <sys/wait.h>
pid_t wait(int * status);
返回值:成功时返回回收子进程的进程号;失败时返回EOF;
若子进程没有结束,父进程一直堵塞;若有多个子进程,那个子进程先结束就先回收;
status 指定用于保存子进程返回值和结束方式的地址;
status 为NULL表示直接释放子进程的PCB,不接收返回值;
eg:
int status;
pid_t pid;
if ((pid = fork()) < 0) {
perror(“fork”); exit(-1);
}
else if (pid == 0) {
sleep(1); exit(2);
}
else {
wait(&status); printf(“%x\n”, status)
}
进程返回值和结束方式:
(2) waitpid
函数:
#include <sys/wait.h>
pid_t waitpid(pid_t pid ,int* status, int option);
返回值:成功时返回回收的子进程的pid或0;失败时返回EOF;
参数:
pid 可用于指定回收哪个子进程或任意子进程;
status 指定用于保存子进程返回值和结束方式的地址;
option 指定收回方式,0或WNOHANG(不管回收的进程是否结束都回收);
eg:
6.exec函数族
进程调用exec函数族执行某个程序;进程当前内容被指定的程序替换;实现让父子进程执行不同的程序。
(1)execl /execlp
#include <unistd.h>
int execl(const char *path, const char *arg, …);
int execlp(const char *file, const char *arg, …); //需要使用环境变量
返回值:成功时执行指定的程序;失败返回EOF;
参数:
path 执行的程序名称,包含路径
arg... 传递给执行的程序的参数列表
file 执行的程序的名称,在PATH中查找
eg:
(2)execv /execvp
和execl函数的区别在于将参数封装成指针数组
函数:
#include <unistd.h>
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);
返回值:成功时执行指定的程序;失败时返回EOF;
参数:arg...封装成指针数组的形式。
eg:
(3)system
函数:
#include <stdlib.h>
int system(const char* command);
返回值:成功时返回命令command的返回值;失败时返回EOF;
当前进程等待command执行结束后才继续执行。
注意事项:
两个函数区别execlp不需要写文件名全路径,在PATH查找
最后一个参数必须用空指针(NULL)作结束
进程当前内容被指定的程序替换,但进程号不变
第0个参数必须要写,虽然它没有使用
7.守护进程(Deamon Process)
守护进程:守护进程又叫精灵进程(Daemon Process),它是一个生存期较长的进程,通常独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件。
特点:
始终在后台运行,独立于任何终端,周期性的执行某种任务或等待处理特定事件。它是个特殊的孤儿进程,这种进程脱离终端,为什么要脱离终端呢?之所以脱离于终端是为了避免进程被任何终端所产生的信息所打断,其在执行过程中的信息也不在任何终端上显示。由于在 Linux 中,每一个系统与用户进行交流的界面称为终端,每一个从此终端开始运行的进程都会依附于这个终端,这个终端就称为这些进程的控制终端,当控制终端被关闭时,相应的进程都会自动关闭。
守护进程创建:
(1)创建子进程,父进程退出:
if (fork() > 0){
exit(0);
}
子进程变成孤儿进程,被init进程收养;子进程在后台运行。
(2)子进程创建新会话:setsid()
if (setsid() < 0) {
exit(-1);
}
子进程成为新的会话组长;子进程脱离原先的终端。
(3)改变当前工作目录
chdir("/");
chdir("/tmp");
守护进程一直在后台运行,其工作目录不能被卸载;重新设定当前工作目录cwd.
(4)重设文件权限掩码
if (umask(0) < 0){
exit(-1);
}
文件掩码权限设置为0;只影响当前进程。
(5)关闭打开的文件描述符
int i;
for( i=0 ; i< 3;i++){
close(i);
}
关闭所有从父进程继承的打开文件;已脱离终端,stdin/stdout/stderr无法再使用。
eg:
创建守护进程,每隔1秒将系统时间写入文件time.log 。
8.GDB调试多进程程序
set follow-fork-mode child 设置GDB调试子进程
set follow-fork-mode parent 设置GDB调试父进程
set detach-on-fork on/off 设置GDB跟踪调试单个进程或多个
on: 只调试父进程或子进程的其中一个,(根据follow-fork-mode来决定),这是默认的模式
off:父子进程都在gdb的控制之下,其中一个进程正常调试(根据follow-fork-mode来决定),另一个进程会被设置为暂停状态。
info inferiord 显示GDB调试的进程
inferiors 进程序号(1,2,3.....) 切换GDB调试的进程
三、线程
线程查看命令:ps -eLf
1.进程和线程的区别
2.线程的特点
3.线程共享资源
4.线程私有资源
5.linux线程库
使用pthread线程库,在编译时得链接pthread动态库(-lthread);
6.线程创建 pthread_create
返回值:成功时返回0,失败时返回错误码
参数:
thread 线程对象
attr 线程属性,NULL代表默认属性
routine 线程执行的函数
arg 传递给routine的参数,参数是void*,注意传递参数格式。
注意事项:
(1)主进程的退出,它创建的线程也会退出。
(2)线程创建需要时间,如果主进程马上退出,那线程不能得到执行。
7.线程结束 pthread_exit
结束当前进程;retval可被其他进程通过pthread_join获取;线程私有资源被释放。
8.线程查看tid函数
9.线程间参数传递
10.线程回收 pthread_join
对于一个默认属性的线程A来说,线程占用的资源并不会因为执行结束而得到释放,得调用pthread_join函数释放。
返回值:成功时返回0,失败时返回错误码;
thread要收回的线程对象;调用线程阻塞直到thread结束;*retval接收线程trhread的返回值。
11.线程分离 pthread_detach
作用是在线程结束后自动释放线程所占用的系统资源,无需等待主线程回收。
(1)int pthread_detach(pthread_t thread):
成功时返回0;失败返回错误码。
——指定该状态,线程主动于主控线程断开关系。线程结束后(不会产生僵尸线程)。
(2)pthread_attr_t attr; //通过线程属性来设置游离态(分离态)
eg:
12.线程的取消 pthread_cancel
作用:随时杀死一个线程
int pthread_cancel(pthread_t thread);
注意:线程的取消要有取消点才可以,不是说取消就取消,线程的取消点主要是阻塞的系统调用。
如果没有取消点,可以手动设置一个:void pthread_testcancel(void);
设置取消使用或禁止使用:
int pthread_setcancelstate(int state, int *oldstate);
state的参数:
PTHREAD_CANCEL_ENABLE(enable 可以使用)
PTHREAD_CANCEL_DISABLE(disable 不能使用)
设置取消类型:
int pthread_setcanceltype(int type,int* outtype);
PTHREAD_CANCEL_DEFERRED 等到取消点才取消
PTHREAD_CANCEL_ASYNCHRONOUS 目标线程会立即取消
eg:
13.线程的清理 pthread_cleanup_xx
作用:当线程非正常终止,需要清理一些资源。
void pthread_cleanup_push(void(*routine) (void*),void *arg)
void pthread_cleanup_pop(int execute);
成对使用
标签:int,void,通信,线程,pthread,进程,include From: https://blog.csdn.net/weixin_52706451/article/details/136952998