回顾笔记(四):进程内容

1、进程标识符

进程的标识符类型:pid_t

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

       pid_t getpid(void);        // 当前进程pid
       pid_t getppid(void);       // 父进程pid

2、FEW构建unix世界

2.1、fork进程产生

init进程:进程号为1号,是所有进程的祖先进程。
fork之后父子进程代码资源等完全一样。
父子进程区别:
1、返回值不一样;
2、pid与ppid不一样;
3、子进程不继承未决信号和文件锁;
4、子进程资源利用量清零。
在进程fork之前,要把进程所有的流进行刷新! fflush(NULL)

       #include <unistd.h>

       pid_t fork(void);

2.2、wait子进程回收和资源释放

父进程使用wait回收子进程的资源。
如果父进程结束了,子进程没有结束,子进程成为孤儿进程,由init进程对完成资源回收工作。
如果子进程结束了,但是父进程没有调用wait,子进程的资源无法释放成为僵尸进程。

进程分配的三种方法:分块法,交叉分配,池类算法。

       #include <sys/types.h>
       #include <sys/wait.h>

       // 父进程回收子进程资源
       pid_t wait(int *status);                                // 阻塞的
       pid_t waitpid(pid_t pid, int *status, int options);     // 可以非阻塞

/*
       The value of pid can be:

       < -1   meaning wait for any child process whose  process  group  ID  is
              equal to the absolute value of pid.

       -1     meaning wait for any child process.

       0      meaning  wait  for  any  child process whose process group ID is
              equal to that of the calling process.

       > 0    meaning wait for the child whose process  ID  is  equal  to  the
              value of pid.

*/

/*
       WIFEXITED(status)
              returns true if the child terminated normally, that is, by call‐
              ing exit(3) or _exit(2), or by returning from main().


       WEXITSTATUS(status)
              returns  the  exit  status  of  the child.  This consists of the
              least significant 8 bits of the status argument that  the  child
              specified  in  a  call to exit(3) or _exit(2) or as the argument
              for a return statement in main().  This macro should be employed
              only if WIFEXITED returned true.

       WIFSIGNALED(status)
              returns true if the child process was terminated by a signal.

       WTERMSIG(status)
              returns  the  number of the signal that caused the child process
              to terminate.  This macro should be employed only if WIFSIGNALED
              returned true.
*/

/*

       The  value  of  options  is an OR of zero or more of the following con‐
       stants:

       WNOHANG     return immediately if no child has exited.

       WUNTRACED   also return if a child has  stopped  (but  not  traced  via
                   ptrace(2)).   Status for traced children which have stopped
                   is provided even if this option is not specified.

       WCONTINUED (since Linux 2.6.10)
                   also return if a stopped child has been resumed by delivery
                   of SIGCONT.


*/

2.3、exec函数族

在进程镜像替换之前,要把进程所有的流进行刷新! fflush(NULL)

       #include <unistd.h>

       extern char **environ;

       int execl(const char *path, const char *arg, ...);
       int execlp(const char *file, const char *arg, ...);
       int execle(const char *path, const char *arg,
                  ..., char * const envp[]);
       int execv(const char *path, char *const argv[]);
       int execvp(const char *file, char *const argv[]);
       int execvpe(const char *file, char *const argv[],
                   char *const envp[]);

/*
       The  exec() family of functions replaces the current process image with
       a new process image. 
*/

2.4、FEW的组合一个shell示例

示例1:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <wait.h>

int main()
{
	pid_t pid;
	puts("Begin");

	fflush(NULL);

	pid = fork();
	if(pid < 0)
	{
		perror("fork");
		exit(1);
	}

	if(pid == 0)
	{
		execl("/bin/date", "date", "+%s", NULL);
		perror("execl()");
		exit(1);
	}
	
	wait(NULL);

	puts("End");
	exit(0);
}

示例2:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <wait.h>
#include <string.h>

#include <glob.h>


extern char **environ;


#define DELIMS " \t\n"


// 对输入的命令封装成一个结构体
struct cmd_st            
{
	glob_t globres;
};


static void prompt(void)
{
	printf("myshell-0.1$ ");
}

// 对cmd进行解析
static void parse(char *cmd_str, struct cmd_st *cmd)
{
	char *tok;
	int i = 0;
	
	while(1)
	{
		tok = strsep(&cmd_str, DELIMS);    
		if(tok == NULL)
			break;
		if(tok[0] == '\0')                 
			continue;
		glob(tok, GLOB_NOCHECK | GLOB_APPEND * i, NULL, &cmd->globres);    
		i = 1;
	}
}

int main(int argc, char *argv[])
{
	char *cmd_str = NULL;
	size_t cmd_size = 0;
	struct cmd_st cmd;
	pid_t pid;

	while(1)
	{
		prompt();

		if(getline(&cmd_str, &cmd_size, stdin) < 0)    // 从终端接收命令
			break;
	
		parse(cmd_str, &cmd);

		if(0)
		{}
		else
		{
			pid = fork();
			if(pid < 0)
			{
				perror("fork");
				exit(1);
			}

			if(pid == 0)    // 针对外部命令
			{
				execvp(cmd.globres.gl_pathv[0], cmd.globres.gl_pathv);
				perror("execvp");
				exit(1);
			}
			else
			{
				wait(NULL);
			}
		}
	}


	exit(0);
}

3、守护进程

       #include <unistd.h>

       pid_t setsid(void)
/*
       setsid()  creates  a  new  session  if the calling process is not a process
       group leader.  The calling process is the leader of the  new  session,  the
       process  group leader of the new process group, and has no controlling ter‐
       minal.  The process group ID and session ID of the calling process are  set
       to  the  PID  of the calling process.  The calling process will be the only
       process in this new process group and in this new session.

-----------------------------------------------------------------------------------*/

       #include <unistd.h>
       
       int setpgid(pid_t pid, pid_t pgid);
       pid_t getpgid(pid_t pid);

4、系统日志

       #include <syslog.h>

       // opens a connection to the system logger for a program.
       void openlog(const char *ident, int option, int facility);
       // generates a log message, which will be distributed by syslogd
       void syslog(int priority, const char *format, ...);
       void closelog(void);

/*
   option
        
        ...

       LOG_PID        Include PID with each message.

        ...

    facility

        ...

       LOG_DAEMON     system daemons without separate facility value

        ...

    level

       LOG_EMERG      system is unusable

       LOG_ALERT      action must be taken immediately

       LOG_CRIT       critical conditions

       LOG_ERR        error conditions

       LOG_WARNING    warning conditions

       LOG_NOTICE     normal, but significant, condition

       LOG_INFO       informational message

       LOG_DEBUG      debug-level message

*/

系统日志示例:

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <syslog.h>
#include <string.h>
#include <errno.h>

#define FNAME "/tmp/out"

static int daemonize(void)
{
	int fd;
	pid_t pid;

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

	if(pid > 0)
		exit(0);

	fd = open("/dev/null", O_RDWR);
	if(fd < 0)
		return -1;
	
	dup2(fd, 0);
	dup2(fd, 1);
	dup2(fd, 2);
	
	setsid();

	chdir("/");

	return 0;
}


int main()
{
	FILE *fp;
	int i;
	
	openlog("mydaemon", LOG_PID, LOG_DAEMON);
	if(daemonize())
	{
		syslog(LOG_ERR, "daemonize() failed!");
		exit(1);
	}
	else
	{
		syslog(LOG_INFO, "daemonize() start!");
	}

	if(daemonize())
	{
		exit(1);
	}

	fp = fopen(FNAME, "w");
	if(fp < 0)
	{
		syslog(LOG_ERR, "fopen failed: %s.", strerror(errno));
		exit(1);
	}

	syslog(LOG_INFO, "%s was opened.", FNAME);

	for(i = 0; ; i++)
	{
		fprintf(fp, "%d\n", i);
		fflush(fp);
		syslog(LOG_DEBUG, "%d is printed.", i);
		sleep(1);
	}

	exit(0);
}

单实例守护进程:锁文件/var/run/name.pid
启动脚本文件:/etc/rc*


总结

以上是自己对进程内容的总结,后续还会在此基础上慢慢的补充和完善。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值