目录(?)[+]
一、程序存储
经常被问到进程与线程的区别,今天有人问程序与进程的区别,一下子还真没反应过来 。程序只是一组指令的有序集合,它本身没有任何运行的含义,它只是一个静态的实体。而进程则不同,它是程序在某个数据集上的执行。进程是一个动态的实体,它有自己的生命周期。反映了一个程序在一定的数据集上运行的全部动态过程。
二、crontab
基本格式 :
* * * * * command
分 时 日 月 周 命令第1列表示分钟1~59 每分钟用*或者 */1表示
第2列表示小时1~23(0表示0点)
第3列表示日期1~31
第4列表示月份1~12
第5列标识号星期0~6(0表示星期天)
第6列要运行的命令
在终端输入:crontab -e
然后编辑内容为:* * 9 10 0 echo "now the time is .... `date` " >>/home/fsy/io/tempfile
查看:crontab -l
删除:crontab -r
三、关于fork 进程的补充
1、用重定向方式输出时应该注意:调用fork的程序,会完全复制一个父进程。所以也会复制一个缓冲区,及如果父进程在缓冲区中有内容,则子进程也会一并获得。那为什么对文件的读写不是两个文件呢?因为子进程复制的是文件标示符,转成文件指针会指向同一个文件。
2、fork用于父子进程同时指行不同的代码段,比如网络服务进程。或用于要执行一个不同的程序,通常是子进程从fork返回后立即调用exec。
3、vfrok()不复制父进程的地址空间。子进程一定是先运行。在调用exec/exit之前,它在父进程的空间中运行。
四、exec族
函数还真多,就是功能都一样。一大家子人,长的还差不多,只能干一样事。这存在感,真服了
个人感觉记住一个就行:execlp("ls","ls","-l",NULL);
错误判断:
errno=ENOENT 找不到文件或路径
errno=EFAULT argv/envp忘记用NULL结束
errno=EACCES 没有运行权限
五、exit()与_exit()
最好使用exit()退出程序。因为会清空缓存。exit()在
中。_exit()在 中。中间的参数,可以用wait系统调用接收子进程返回值。
六、wait与waitpid()
wait()使父进程阻塞直到子进程结束才返回。wait()是waitpid()的一个特例。所以waitpid()更牛一些~
通常说来waitpid(),用于等待一个特定的子进程。调用方法为:waitpid(pid1, &stu, WNOHANG) 或者 waitpid(pid1, NULL, 0)
七、孤儿与僵尸(进程)
这个...不知道是作者有才,还是翻译有思想,弄出了这么俩词
父进程先死了,子进程就是孤儿了。但是别担心,咱是和 *谐社会,怎么能有孤儿呢?所以马上有个大爹——init 收养这些没人要的进程。
要是子进程先死了,父进程没回收子进程,那他就成了孤魂野鬼。也就变僵尸了 所以父进程要收尸啊...... 这个也好解决。收尸其实也不费劲,调用wait()/waitpid()就行。这个到处都是僵尸,对社会的安定团结还是有很大影响的。系统所能使用的进程号是有限的,子进程不回收,虽然不占内存了,但是进程号还占着,僵尸多了,正常的子进程就没有进程号了......
一、进程组与会话
进程组:是一个或多个进程的集合。可以调用 getpgid(0) 或 getpgrp() 来得到。进程组ID为组长的进程ID。只要进程组中有一个进程存在,进程组就存在,与组长进程是否终止无关。调用 setpgid() 加入一个现有的进程组或创建一个新的进程组。
会话:一个或多个进程组的集合
可以用 setsid() 建立新会话,则该进程会变成新会话的首进程,同时成为一个新进程组的组长进程,该进程没有控制终端。
二、守护进程
守护进程的特点:没有终端的限制,不受用户、终端或其它的变化而受到影响。
创建守护进程的步骤:
出错处理:因为守护进程不依赖于终端,所以出错信息是不能用 printf 滴,这..... 怎么办?莫怕,用 syslog() 就能搞定~
用系统日志就要调用三个函数:openlog()、syslog()、closelog() 系统日志存于 /var/log/messages
举例:
[cpp] view plaincopyprint?[cpp] view plaincopyprint?
- #include
- #include
- #include
- #include
- int main(){
- pid_t pid,s;
- int i;
- char *buff="Daemon Test!\n";
- if((pid = fork())<0){
- printf("fork error!\n");
- exit(1);
- }else if(pid> 0){
- exit(0);
- }
- //第一个参数为在消息之前加入的字符串,第二个参数在每个消息中包含进程的ID,第三个参数指定程序发送的消息类型
- openlog("daemon_testlog",LOG_PID,LOG_DAEMON);
- if((s=setsid())<0){
- //第一个参数为参数类型,第二个参数为信息字符串
- syslog(LOG_ERR,"%s\n","setsid error!");
- }
- chdir("/");
- umask(0);
- for(i=0;i
//关闭文件描述 - close(i);
- }
- while(1){
- syslog(LOG_INFO,"%s\n",buff);
- sleep(10);
- }
- closelog();
- return 0;
- }
- #include
- #include
- #include
- #include
- int main(){
- pid_t pid,s;
- int i;
- char *buff="Daemon Test!\n";
- if((pid = fork())<0){
- printf("fork error!\n");
- exit(1);
- }else if(pid> 0){
- exit(0);
- }
- //第一个参数为在消息之前加入的字符串,第二个参数在每个消息中包含进程的ID,第三个参数指定程序发送的消息类型
- openlog("daemon_testlog",LOG_PID,LOG_DAEMON);
- if((s=setsid())<0){
- //第一个参数为参数类型,第二个参数为信息字符串
- syslog(LOG_ERR,"%s\n","setsid error!");
- }
- chdir("/");
- umask(0);
- for(i=0;i
//关闭文件描述 - close(i);
- }
- while(1){
- syslog(LOG_INFO,"%s\n",buff);
- sleep(10);
- }
- closelog();
- return 0;
- }
三、信号
Linux对每种信号都制定了默认的操作。捕捉到信号可以采用默认的操作、可以忽略(SIGKILL 与 SIGSTOP除外)、也可以执行相应的自定义处理函数。
kill()、raise() 发信号。一些相关知识可以参考 Linux 信号通信
pause() 将进程挂起直到捕捉到信号为止。
举例1:
[cpp] view plaincopyprint?
[cpp] view plaincopyprint?
- #include
- #include
- #include
- void my_func(int);
- int main() {
- printf("Wainting for signal: SIGINT/SIGQUIT...\n");
- signal(SIGINT,my_func);
- signal(SIGQUIT,my_func);
- pause();
- pause();
- exit(0);
- }
- void my_func(int sign_no){
- if (sign_no==SIGINT) {
- printf("I got CTRL+C!\n");
- } else if (sign_no==SIGQUIT) {
- printf("I got CTRL+\\!\n");
- }
- }
- #include
- #include
- #include
- void my_func(int);
- int main() {
- printf("Wainting for signal: SIGINT/SIGQUIT...\n");
- signal(SIGINT,my_func);
- signal(SIGQUIT,my_func);
- pause();
- pause();
- exit(0);
- }
- void my_func(int sign_no){
- if (sign_no==SIGINT) {
- printf("I got CTRL+C!\n");
- } else if (sign_no==SIGQUIT) {
- printf("I got CTRL+\\!\n");
- }
- }
举例2:
[cpp] view plaincopyprint?[cpp] view plaincopyprint?
- #include
- #include
- #include
- #include
- int main(){
- pid_t pid;
- if((pid = fork())<0){
- printf("fork error!\n");
- exit(1);
- }else if(pid == 0){
- printf("Child process wait for singal....a\n");
- raise(SIGSTOP); //子进程向自己发送一个消息,线程停止
- printf("Child is dead\n"); //此句不会打出来,因为进程直接被kill了
- }else{
- sleep(10);
- kill(pid,SIGKILL);
- wait(NULL);
- }
- return 0;
- }
- #include
- #include
- #include
- #include
- int main(){
- pid_t pid;
- if((pid = fork())<0){
- printf("fork error!\n");
- exit(1);
- }else if(pid == 0){
- printf("Child process wait for singal....a\n");
- raise(SIGSTOP); //子进程向自己发送一个消息,线程停止
- printf("Child is dead\n"); //此句不会打出来,因为进程直接被kill了
- }else{
- sleep(10);
- kill(pid,SIGKILL);
- wait(NULL);
- }
- return 0;
- }
alarm() 在进程中设置一个定时器,当时间到时,发出SIGALARM信号。一个进程只能有一个闹钟时间,新的将代替旧的。返回值为新旧时间差值。
举例:
[cpp] view plaincopyprint?[cpp] view plaincopyprint?
- #include
- #include
- #include
- #include
- int main(){
- int ret=alarm(5);
- printf("alarm...%d\n",ret);
- sleep(3);
- ret=alarm(5);
- printf("alarm...%d\n",ret);
- pause();
- printf("never show\n");
- }
- #include
- #include
- #include
- #include
- int main(){
- int ret=alarm(5);
- printf("alarm...%d\n",ret);
- sleep(3);
- ret=alarm(5);
- printf("alarm...%d\n",ret);
- pause();
- printf("never show\n");
- }
程序运行结果为:alarm...0 alarm....2 。 2为相差时间,程序收到SIGALARM默认执行的操作为终止线程。
sigaction()函数:signal()的高级版~
例子:
[cpp] view plaincopyprint?[cpp] view plaincopyprint?
- #include
- #include
- #include
- #include
- void my_func(int);
- int main(){
- struct sigaction sa,oldsa;
- printf("waiting for SIGINT/SIGQUIT......\n");
- sa.sa_handler=my_func; //设定处理函数
- sigemptyset(&sa.sa_mask); //清空信号集合
- sa.sa_flags=0; //对信号处理的选项一般设为0
- sigaction(SIGINT,&sa,&oldsa); //oldsa为保存旧的信号结构体
- sigaction(SIGQUIT,&sa,&oldsa);
- pause();
- pause();
- pause();
- pause();
- pause();
- pause();
- pause();
- }
- void my_func(int sig){
- if(sig == SIGINT){
- printf("Receive CTRL+C!\n");
- }
- else if(sig == SIGQUIT){
- printf("Receive CTRL+\\!\n");
- }else
- printf("Receive Signal!\n");
- }
- #include
- #include
- #include
- #include
- void my_func(int);
- int main(){
- struct sigaction sa,oldsa;
- printf("waiting for SIGINT/SIGQUIT......\n");
- sa.sa_handler=my_func; //设定处理函数
- sigemptyset(&sa.sa_mask); //清空信号集合
- sa.sa_flags=0; //对信号处理的选项一般设为0
- sigaction(SIGINT,&sa,&oldsa); //oldsa为保存旧的信号结构体
- sigaction(SIGQUIT,&sa,&oldsa);
- pause();
- pause();
- pause();
- pause();
- pause();
- pause();
- pause();
- }
- void my_func(int sig){
- if(sig == SIGINT){
- printf("Receive CTRL+C!\n");
- }
- else if(sig == SIGQUIT){
- printf("Receive CTRL+\\!\n");
- }else
- printf("Receive Signal!\n");
- }
信号集
通常就是这个步骤。清空信号集->添加信号->设置信号屏蔽->定义信号处理
举例:
[cpp] view plaincopyprint?
- #include
- #include
- #include
- #include
- #include
- void my_func(int);
- int main() {
- struct sigaction sa1,sa2;
- sigset_t set;
- //清空
- if (sigemptyset(&set)<0) {
- var cpro_id = "u6885494";