linux进程学习

来源:互联网 发布:mac excel快捷键大全 编辑:程序博客网 时间:2024/06/05 08:52

进程
是一个动态的实体,是程序的一次执行过程。
进程和程序的区别在于:进程是动态的,程序是静态的。


为了让计算机在同一时间内能执行更多任务,在进程内部又划分了话多线程。
线程在进程的内部,它是比进程更小的能独立运行的基本单位。


线程基本上不拥有系统资源,它与同属一个进程的其他线程共享进程拥有的全部资源。


进程在执行过程中拥有独立的内存单元,其内部的线程共享进些内存。
一个线程可以创建和撤消另一个线线,同一个进程中的多个线程可以并行执行。


进程标识
#include <unistd.h>
pid_t getpid();//获得进程ID
pid_t getppid();//获得父进程ID
pid_t getuid();//获得进程的实际用户ID
pid_t geteuid();//获得进程有效用户ID
pid_t getgid();//获得进程的实际组ID
pid_t getegid();//获得进程的有效组ID

linux进程结构
代码段:存放可执行代码
数据段:程序的全局变量,常量,静态变量
堆栈段:动态分配的内存变量,函数调用,参数等


linux进程状态
运行状态Runnable
可中断等待状态Sleeping
不可中断等待状态Duninterruptible sleep
僵死状态Zombile
停止状态Traced or stopped


进程控制
创建进程,执行新程序,退出进程及改变进程优先级等。


fork:创建一个新进程
exit:终止进程
exec:执行一个应用程序
wait:将父进程挂起,等待子进程终止
getpid:获得当前进程的进程ID
nice:改变优先级


创建进程:fork是创建新进程的唯一方法
想父进程等待子进程执行完毕后再执行,可以fork后调用wait/waitpid


#include <sys/types.h>
#include <unistd.h>
pid_t fork(void);


#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

int main()
{
  pid_t pid;
  printf("Process Creation Study\n");
  pid = fork();
  switch(pid)
  {
        case 0:
                printf("Child progress,CurPid is %d,ParentPid is %d\n",pid,getppid());
                break;
        case -1:
                perror("process error\n");
                break;
        default:
                printf("Parend process,ChildPid is %d,ParentPid is %d\n",pid,getpid());
                break;
  }
  exit(0);
}


函数最多一个返回值,但fork函数非常特殊,它有两个返回值,即调用一次返回两次。成功调用fork后,当前进程实际上已经分裂成两个进程,一个原父进程,另一个刚刚创建的子进程。
子进程返回0
父进程返回新创建子进程的ID


vfork创建的子进程共享父进程的地址空间,任何数据修改同样为父进程所见,保证子进程先运行,当它调用exec/exit后,父进程才可能被调度运行。


fork子进程会复制父进程资源,开销大,
vfork不会拷贝父进程的地址空间,减小了开销


创建守护进程
在后台运行,没有控制终端与之相连的进程,它独立于控制终端,通常周期性地执行某种任务。


启动方式:
从启动脚本/etc/rc.d中启动
作业规划进程cron启动
用户终端执行


创建守护进程
1用fork产生一个子进程,然后使父进程退出
2调用setsid创建一个新对话期,
3关闭不再需要的文件描述符
4将当前目录改为根目录
5将文件创建时使用的屏蔽字设置为0
6处理SIGCHLD信号


#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <time.h>
#include <syslog.h>


int init_daemon()
{
        int pid;
        int i;


        signal(SIGTTOU,SIG_IGN);
        signal(SIGTTIN,SIG_IGN);
        signal(SIGTSTP,SIG_IGN);
        signal(SIGHUP,SIG_IGN);


    pid = fork();
        if(pid>0)
                exit(0);
        else if(pid <0)
                return -1;


        setsid();


        pid = fork();
        if(pid>0)
                exit(0);
        else if(pid <0)
                return -1;


        for(i=0;i < NOFILE ; close(i++));

        chdir("/");

        umask(0);

        signal(SIGCHLD,SIG_IGN);

        return 0;
}


int main()
{
        time_t now;
        init_daemon();
        syslog(LOG_USER|LOG_INFO,"test deamon!\n");
        while(1)
        {
                        sleep(8);
                        time(&now);
                        syslog(LOG_USER | LOG_INFO,"daemon time :%s\n",ctime(&now));
        }
}


在使用syslog函数前,首先需要配置/etc/syslog.conf,在该文件最后加
user.*/var/log/test.log,然后重新启动syslog服务。
/etc/init.d/syslog stop
/etc/init.d/syslog start
这样信息就会写入test.log中。



进程退出表示进程结束运行。
正常退出
main执行return 
exit
_exit


异常退出
about


执行新程序
子进程通常会调用exec来执行另一个程序
exec调用并没有生成新进程,一个进程一旦调用exec,它本身就死亡了。


#include <unistd.h>
int execve(const char* path,char* const argv[],char * const envp[]);
int execv(const char *path,char* const envp[]);
int execle(const char *path,const char * arg,...);
int execl(const cahr *path,const char* arg,...);
int exevp(const char *file,char * const argv[]);
int execlp(const char *file,const char* arg,...);


env命令查看环境变量

exec函数族可以执行二进制可执行文件,也可以执行SHELL:开头#!/bin/sh


等待进程结束
#include <sys/types.h>
#include <sys/wait.h>
pid_t wait(int *statloc);
pid_t waitpid(pid_t pid,int *statloc,int options);


#include <sys/types.h>
#include <unistd.h>
int setuid(uid_t uid);
int setgid(gid_t gid);


改变进程的优先级
#include <unistd.h>
int nice(int increment);


#include <sys/resource.h>
int getpriority(int which,int who);

int setpriority(int which,int who,int prio);


保存,方便查阅使用。


0 0
原创粉丝点击