• 进程的描述和进程的创建


    2018-2019-120189224 《庖丁解牛Iinux内核分析》第七周学习总结

    进程的描述


    j进程的创建

    fork创建了两个进程,一个父进程,一个子进程,其中子进程是对父进程的拷贝,它从父进程处复制了整个进程的地址空间,只有进程号和一些计时器等等是自己独有的,由于要复制很多资源,所以fork创建进程是很慢的。fork执行一次有两次返回值,在父进程里返回新建的子进程编号,在子进程里返回0。进程创建相关代码如下:

    /*
    1694 * Create a kernel thread.
    1695 */
    1696pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
    1697{
    1698	return do_fork(flags|CLONE_VM|CLONE_UNTRACED, (unsigned long)fn,
    1699		(unsigned long)arg, NULL, NULL);
    1700}
    1701
    1702#ifdef __ARCH_WANT_SYS_FORK
    1703SYSCALL_DEFINE0(fork)
    1704{
    1705#ifdef CONFIG_MMU
    1706	return do_fork(SIGCHLD, 0, 0, NULL, NULL);
    1707#else
    1708	/* can not support in nommu mode */
    1709	return -EINVAL;
    1710#endif
    1711}
    1712#endif
    1713
    1714#ifdef __ARCH_WANT_SYS_VFORK
    1715SYSCALL_DEFINE0(vfork)
    1716{
    1717	return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, 0,
    1718			0, NULL, NULL);
    1719}
    1720#endif
    1721
    1722#ifdef __ARCH_WANT_SYS_CLONE
    1723#ifdef CONFIG_CLONE_BACKWARDS
    1724SYSCALL_DEFINE5(clone, unsigned long, clone_flags, unsigned long, newsp,
    1725		 int __user *, parent_tidptr,
    1726		 int, tls_val,
    1727		 int __user *, child_tidptr)
    1728#elif defined(CONFIG_CLONE_BACKWARDS2)
    1729SYSCALL_DEFINE5(clone, unsigned long, newsp, unsigned long, clone_flags,
    1730		 int __user *, parent_tidptr,
    1731		 int __user *, child_tidptr,
    1732		 int, tls_val)
    1733#elif defined(CONFIG_CLONE_BACKWARDS3)
    1734SYSCALL_DEFINE6(clone, unsigned long, clone_flags, unsigned long, newsp,
    1735		int, stack_size,
    1736		int __user *, parent_tidptr,
    1737		int __user *, child_tidptr,
    1738		int, tls_val)
    1739#else
    1740SYSCALL_DEFINE5(clone, unsigned long, clone_flags, unsigned long, newsp,
    1741		 int __user *, parent_tidptr,
    1742		 int __user *, child_tidptr,
    1743		 int, tls_val)
    1744#endif
    1745{
    1746	return do_fork(clone_flags, newsp, 0, parent_tidptr, child_tidptr);
    1747}
    1748#endif
    

    由于创建进程的三种方式最终都是调用do_fork,所以我们分析do_fork的源码:

    long do_fork(unsigned long clone_flags,
    1624	      unsigned long stack_start,
    1625	      unsigned long stack_size,
    1626	      int __user *parent_tidptr,
    1627	      int __user *child_tidptr)
    1628{
    1629	struct task_struct *p;
    1630	int trace = 0;
    1631	long nr;
    1632
    1633	/*
    1634	 * Determine whether and which event to report to ptracer.  When
    1635	 * called from kernel_thread or CLONE_UNTRACED is explicitly
    1636	 * requested, no event is reported; otherwise, report if the event
    1637	 * for the type of forking is enabled.
    1638	 */
    1639	if (!(clone_flags & CLONE_UNTRACED)) {
    1640		if (clone_flags & CLONE_VFORK)
    1641			trace = PTRACE_EVENT_VFORK;
    1642		else if ((clone_flags & CSIGNAL) != SIGCHLD)
    1643			trace = PTRACE_EVENT_CLONE;
    1644		else
    1645			trace = PTRACE_EVENT_FORK;
    1646
    1647		if (likely(!ptrace_event_enabled(current, trace)))
    1648			trace = 0;
    1649	}
    1650
    1651	p = copy_process(clone_flags, stack_start, stack_size,
    1652			 child_tidptr, NULL, trace);
    1653	/*
    1654	 * Do this prior waking up the new thread - the thread pointer
    1655	 * might get invalid after that point, if the thread exits quickly.
    1656	 */
    1657	if (!IS_ERR(p)) {
    1658		struct completion vfork;
    1659		struct pid *pid;
    1660
    1661		trace_sched_process_fork(current, p);
    1662
    1663		pid = get_task_pid(p, PIDTYPE_PID);
    1664		nr = pid_vnr(pid);
    1665
    1666		if (clone_flags & CLONE_PARENT_SETTID)
    1667			put_user(nr, parent_tidptr);
    1668
    1669		if (clone_flags & CLONE_VFORK) {
    1670			p->vfork_done = &vfork;
    1671			init_completion(&vfork);
    1672			get_task_struct(p);
    1673		}
    1674
    1675		wake_up_new_task(p);
    1676
    1677		/* forking complete and child started to run, tell ptracer */
    1678		if (unlikely(trace))
    1679			ptrace_event_pid(trace, pid);
    1680
    1681		if (clone_flags & CLONE_VFORK) {
    1682			if (!wait_for_vfork_done(p, &vfork))
    1683				ptrace_event_pid(PTRACE_EVENT_VFORK_DONE, pid);
    1684		}
    1685
    1686		put_pid(pid);
    1687	} else {
    1688		nr = PTR_ERR(p);
    1689	}
    1690	return nr;
    1691}
    

    do_fork主要完成了copy_process的调用,来复制父进程

    82static struct task_struct *copy_process(unsigned long clone_flags,
    1183					unsigned long stack_start,
    1184					unsigned long stack_size,
    1185					int __user *child_tidptr,
    1186					struct pid *pid,
    1187					int trace)
    1188{
    1189	int retval;
    1190	struct task_struct *p;
    1191
    1192	if ((clone_flags & (CLONE_NEWNS|CLONE_FS)) == (CLONE_NEWNS|CLONE_FS))
    1193		return ERR_PTR(-EINVAL);
    1194
    1195	if ((clone_flags & (CLONE_NEWUSER|CLONE_FS)) == (CLONE_NEWUSER|CLONE_FS))
    1196		return ERR_PTR(-EINVAL);
    1197
    1198	/*
    1199	 * Thread groups must share signals as well, and detached threads
    1200	 * can only be started up within the thread group.
    1201	 */
    1202	if ((clone_flags & CLONE_THREAD) && !(clone_flags & CLONE_SIGHAND))
    1203		return ERR_PTR(-EINVAL);
    1204
    1205	/*
    1206	 * Shared signal handlers imply shared VM. By way of the above,
    1207	 * thread groups also imply shared VM. Blocking this case allows
    1208	 * for various simplifications in other code.
    1209	 */
    1210	if ((clone_flags & CLONE_SIGHAND) && !(clone_flags & CLONE_VM))
    1211		return ERR_PTR(-EINVAL);
    1212
    1213	/*
    1214	 * Siblings of global init remain as zombies on exit since they are
    1215	 * not reaped by their parent (swapper). To solve this and to avoid
    1216	 * multi-rooted process trees, prevent global and container-inits
    1217	 * from creating siblings.
    1218	 */
    1219	if ((clone_flags & CLONE_PARENT) &&
    1220				current->signal->flags & SIGNAL_UNKILLABLE)
    1221		return ERR_PTR(-EINVAL);
    1222
    1223	/*
    1224	 * If the new process will be in a different pid or user namespace
    1225	 * do not allow it to share a thread group or signal handlers or
    1226	 * parent with the forking task.
    1227	 */
    1228	if (clone_flags & CLONE_SIGHAND) {
    1229		if ((clone_flags & (CLONE_NEWUSER | CLONE_NEWPID)) ||
    1230		    (task_active_pid_ns(current) !=
    1231				current->nsproxy->pid_ns_for_children))
    1232			return ERR_PTR(-EINVAL);
    1233	}
    1234
    1235	retval = security_task_create(clone_flags);
    1236	if (retval)
    1237		goto fork_out;
    1238
    1239	retval = -ENOMEM;
    1240	p = dup_task_struct(current);
    1241	if (!p)
    1242		goto fork_out;
    1243
    1244	ftrace_graph_init_task(p);
    1245
    1246	rt_mutex_init_task(p);
    1247
    1248#ifdef CONFIG_PROVE_LOCKING
    1249	DEBUG_LOCKS_WARN_ON(!p->hardirqs_enabled);
    1250	DEBUG_LOCKS_WARN_ON(!p->softirqs_enabled);
    1251#endif
    1252	retval = -EAGAIN;
    1253	if (atomic_read(&p->real_cred->user->processes) >=
    1254			task_rlimit(p, RLIMIT_NPROC)) {
    1255		if (p->real_cred->user != INIT_USER &&
    1256		    !capable(CAP_SYS_RESOURCE) && !capable(CAP_SYS_ADMIN))
    1257			goto bad_fork_free;
    1258	}
    1259	current->flags &= ~PF_NPROC_EXCEEDED;
    1260
    1261	retval = copy_creds(p, clone_flags);
    1262	if (retval < 0)
    1263		goto bad_fork_free;
    1264
    1265	/*
    1266	 * If multiple threads are within copy_process(), then this check
    1267	 * triggers too late. This doesn't hurt, the check is only there
    1268	 * to stop root fork bombs.
    1269	 */
    1270	retval = -EAGAIN;
    1271	if (nr_threads >= max_threads)
    1272		goto bad_fork_cleanup_count;
    1273
    1274	if (!try_module_get(task_thread_info(p)->exec_domain->module))
    1275		goto bad_fork_cleanup_count;
    1276
    1277	delayacct_tsk_init(p);	/* Must remain after dup_task_struct() */
    1278	p->flags &= ~(PF_SUPERPRIV | PF_WQ_WORKER);
    1279	p->flags |= PF_FORKNOEXEC;
    1280	INIT_LIST_HEAD(&p->children);
    1281	INIT_LIST_HEAD(&p->sibling);
    1282	rcu_copy_process(p);
    1283	p->vfork_done = NULL;
    1284	spin_lock_init(&p->alloc_lock);
    1285
    1286	init_sigpending(&p->pending);
    1287
    1288	p->utime = p->stime = p->gtime = 0;
    1289	p->utimescaled = p->stimescaled = 0;
    1290#ifndef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
    1291	p->prev_cputime.utime = p->prev_cputime.stime = 0;
    1292#endif
    1293#ifdef CONFIG_VIRT_CPU_ACCOUNTING_GEN
    1294	seqlock_init(&p->vtime_seqlock);
    1295	p->vtime_snap = 0;
    1296	p->vtime_snap_whence = VTIME_SLEEPING;
    1297#endif
    1298
    1299#if defined(SPLIT_RSS_COUNTING)
    1300	memset(&p->rss_stat, 0, sizeof(p->rss_stat));
    1301#endif
    1302
    1303	p->default_timer_slack_ns = current->timer_slack_ns;
    1304
    1305	task_io_accounting_init(&p->ioac);
    1306	acct_clear_integrals(p);
    1307
    1308	posix_cpu_timers_init(p);
    1309
    1310	p->start_time = ktime_get_ns();
    1311	p->real_start_time = ktime_get_boot_ns();
    1312	p->io_context = NULL;
    1313	p->audit_context = NULL;
    1314	if (clone_flags & CLONE_THREAD)
    1315		threadgroup_change_begin(current);
    1316	cgroup_fork(p);
    1317#ifdef CONFIG_NUMA
    1318	p->mempolicy = mpol_dup(p->mempolicy);
    1319	if (IS_ERR(p->mempolicy)) {
    1320		retval = PTR_ERR(p->mempolicy);
    1321		p->mempolicy = NULL;
    1322		goto bad_fork_cleanup_threadgroup_lock;
    1323	}
    1324#endif
    1325#ifdef CONFIG_CPUSETS
    1326	p->cpuset_mem_spread_rotor = NUMA_NO_NODE;
    1327	p->cpuset_slab_spread_rotor = NUMA_NO_NODE;
    1328	seqcount_init(&p->mems_allowed_seq);
    1329#endif
    1330#ifdef CONFIG_TRACE_IRQFLAGS
    1331	p->irq_events = 0;
    1332	p->hardirqs_enabled = 0;
    1333	p->hardirq_enable_ip = 0;
    1334	p->hardirq_enable_event = 0;
    1335	p->hardirq_disable_ip = _THIS_IP_;
    1336	p->hardirq_disable_event = 0;
    1337	p->softirqs_enabled = 1;
    1338	p->softirq_enable_ip = _THIS_IP_;
    1339	p->softirq_enable_event = 0;
    1340	p->softirq_disable_ip = 0;
    1341	p->softirq_disable_event = 0;
    1342	p->hardirq_context = 0;
    1343	p->softirq_context = 0;
    1344#endif
    1345#ifdef CONFIG_LOCKDEP
    1346	p->lockdep_depth = 0; /* no locks held yet */
    1347	p->curr_chain_key = 0;
    1348	p->lockdep_recursion = 0;
    1349#endif
    1350
    1351#ifdef CONFIG_DEBUG_MUTEXES
    1352	p->blocked_on = NULL; /* not blocked yet */
    1353#endif
    1354#ifdef CONFIG_BCACHE
    1355	p->sequential_io	= 0;
    1356	p->sequential_io_avg	= 0;
    1357#endif
    1358
    1359	/* Perform scheduler related setup. Assign this task to a CPU. */
    1360	retval = sched_fork(clone_flags, p);
    1361	if (retval)
    1362		goto bad_fork_cleanup_policy;
    1363
    1364	retval = perf_event_init_task(p);
    1365	if (retval)
    1366		goto bad_fork_cleanup_policy;
    1367	retval = audit_alloc(p);
    1368	if (retval)
    1369		goto bad_fork_cleanup_perf;
    1370	/* copy all the process information */
    1371	shm_init_task(p);
    1372	retval = copy_semundo(clone_flags, p);
    1373	if (retval)
    1374		goto bad_fork_cleanup_audit;
    1375	retval = copy_files(clone_flags, p);
    1376	if (retval)
    1377		goto bad_fork_cleanup_semundo;
    1378	retval = copy_fs(clone_flags, p);
    1379	if (retval)
    1380		goto bad_fork_cleanup_files;
    1381	retval = copy_sighand(clone_flags, p);
    1382	if (retval)
    1383		goto bad_fork_cleanup_fs;
    1384	retval = copy_signal(clone_flags, p);
    1385	if (retval)
    1386		goto bad_fork_cleanup_sighand;
    1387	retval = copy_mm(clone_flags, p);
    1388	if (retval)
    1389		goto bad_fork_cleanup_signal;
    1390	retval = copy_namespaces(clone_flags, p);
    1391	if (retval)
    1392		goto bad_fork_cleanup_mm;
    1393	retval = copy_io(clone_flags, p);
    1394	if (retval)
    1395		goto bad_fork_cleanup_namespaces;
    1396	retval = copy_thread(clone_flags, stack_start, stack_size, p);
    1397	if (retval)
    1398		goto bad_fork_cleanup_io;
    1399
    1400	if (pid != &init_struct_pid) {
    1401		retval = -ENOMEM;
    1402		pid = alloc_pid(p->nsproxy->pid_ns_for_children);
    1403		if (!pid)
    1404			goto bad_fork_cleanup_io;
    1405	}
    1406
    1407	p->set_child_tid = (clone_flags & CLONE_CHILD_SETTID) ? child_tidptr : NULL;
    1408	/*
    1409	 * Clear TID on mm_release()?
    1410	 */
    1411	p->clear_child_tid = (clone_flags & CLONE_CHILD_CLEARTID) ? child_tidptr : NULL;
    1412#ifdef CONFIG_BLOCK
    1413	p->plug = NULL;
    1414#endif
    1415#ifdef CONFIG_FUTEX
    1416	p->robust_list = NULL;
    1417#ifdef CONFIG_COMPAT
    1418	p->compat_robust_list = NULL;
    1419#endif
    1420	INIT_LIST_HEAD(&p->pi_state_list);
    1421	p->pi_state_cache = NULL;
    1422#endif
    1423	/*
    1424	 * sigaltstack should be cleared when sharing the same VM
    1425	 */
    1426	if ((clone_flags & (CLONE_VM|CLONE_VFORK)) == CLONE_VM)
    1427		p->sas_ss_sp = p->sas_ss_size = 0;
    1428
    1429	/*
    1430	 * Syscall tracing and stepping should be turned off in the
    1431	 * child regardless of CLONE_PTRACE.
    1432	 */
    1433	user_disable_single_step(p);
    1434	clear_tsk_thread_flag(p, TIF_SYSCALL_TRACE);
    1435#ifdef TIF_SYSCALL_EMU
    1436	clear_tsk_thread_flag(p, TIF_SYSCALL_EMU);
    1437#endif
    1438	clear_all_latency_tracing(p);
    1439
    1440	/* ok, now we should be set up.. */
    1441	p->pid = pid_nr(pid);
    1442	if (clone_flags & CLONE_THREAD) {
    1443		p->exit_signal = -1;
    1444		p->group_leader = current->group_leader;
    1445		p->tgid = current->tgid;
    1446	} else {
    1447		if (clone_flags & CLONE_PARENT)
    1448			p->exit_signal = current->group_leader->exit_signal;
    1449		else
    1450			p->exit_signal = (clone_flags & CSIGNAL);
    1451		p->group_leader = p;
    1452		p->tgid = p->pid;
    1453	}
    1454
    1455	p->nr_dirtied = 0;
    1456	p->nr_dirtied_pause = 128 >> (PAGE_SHIFT - 10);
    1457	p->dirty_paused_when = 0;
    1458
    1459	p->pdeath_signal = 0;
    1460	INIT_LIST_HEAD(&p->thread_group);
    1461	p->task_works = NULL;
    1462
    1463	/*
    1464	 * Make it visible to the rest of the system, but dont wake it up yet.
    1465	 * Need tasklist lock for parent etc handling!
    1466	 */
    1467	write_lock_irq(&tasklist_lock);
    1468
    1469	/* CLONE_PARENT re-uses the old parent */
    1470	if (clone_flags & (CLONE_PARENT|CLONE_THREAD)) {
    1471		p->real_parent = current->real_parent;
    1472		p->parent_exec_id = current->parent_exec_id;
    1473	} else {
    1474		p->real_parent = current;
    1475		p->parent_exec_id = current->self_exec_id;
    1476	}
    1477
    1478	spin_lock(&current->sighand->siglock);
    1479
    1480	/*
    1481	 * Copy seccomp details explicitly here, in case they were changed
    1482	 * before holding sighand lock.
    1483	 */
    1484	copy_seccomp(p);
    1485
    1486	/*
    1487	 * Process group and session signals need to be delivered to just the
    1488	 * parent before the fork or both the parent and the child after the
    1489	 * fork. Restart if a signal comes in before we add the new process to
    1490	 * it's process group.
    1491	 * A fatal signal pending means that current will exit, so the new
    1492	 * thread can't slip out of an OOM kill (or normal SIGKILL).
    1493	*/
    1494	recalc_sigpending();
    1495	if (signal_pending(current)) {
    1496		spin_unlock(&current->sighand->siglock);
    1497		write_unlock_irq(&tasklist_lock);
    1498		retval = -ERESTARTNOINTR;
    1499		goto bad_fork_free_pid;
    1500	}
    1501
    1502	if (likely(p->pid)) {
    1503		ptrace_init_task(p, (clone_flags & CLONE_PTRACE) || trace);
    1504
    1505		init_task_pid(p, PIDTYPE_PID, pid);
    1506		if (thread_group_leader(p)) {
    1507			init_task_pid(p, PIDTYPE_PGID, task_pgrp(current));
    1508			init_task_pid(p, PIDTYPE_SID, task_session(current));
    1509
    1510			if (is_child_reaper(pid)) {
    1511				ns_of_pid(pid)->child_reaper = p;
    1512				p->signal->flags |= SIGNAL_UNKILLABLE;
    1513			}
    1514
    1515			p->signal->leader_pid = pid;
    1516			p->signal->tty = tty_kref_get(current->signal->tty);
    1517			list_add_tail(&p->sibling, &p->real_parent->children);
    1518			list_add_tail_rcu(&p->tasks, &init_task.tasks);
    1519			attach_pid(p, PIDTYPE_PGID);
    1520			attach_pid(p, PIDTYPE_SID);
    1521			__this_cpu_inc(process_counts);
    1522		} else {
    1523			current->signal->nr_threads++;
    1524			atomic_inc(&current->signal->live);
    1525			atomic_inc(&current->signal->sigcnt);
    1526			list_add_tail_rcu(&p->thread_group,
    1527					  &p->group_leader->thread_group);
    1528			list_add_tail_rcu(&p->thread_node,
    1529					  &p->signal->thread_head);
    1530		}
    1531		attach_pid(p, PIDTYPE_PID);
    1532		nr_threads++;
    1533	}
    1534
    1535	total_forks++;
    1536	spin_unlock(&current->sighand->siglock);
    1537	syscall_tracepoint_update(p);
    1538	write_unlock_irq(&tasklist_lock);
    1539
    1540	proc_fork_connector(p);
    1541	cgroup_post_fork(p);
    1542	if (clone_flags & CLONE_THREAD)
    1543		threadgroup_change_end(current);
    1544	perf_event_fork(p);
    1545
    1546	trace_task_newtask(p, clone_flags);
    1547	uprobe_copy_process(p, clone_flags);
    1548
    1549	return p;
    1550
    1551bad_fork_free_pid:
    1552	if (pid != &init_struct_pid)
    1553		free_pid(pid);
    1554bad_fork_cleanup_io:
    1555	if (p->io_context)
    1556		exit_io_context(p);
    1557bad_fork_cleanup_namespaces:
    1558	exit_task_namespaces(p);
    1559bad_fork_cleanup_mm:
    1560	if (p->mm)
    1561		mmput(p->mm);
    1562bad_fork_cleanup_signal:
    1563	if (!(clone_flags & CLONE_THREAD))
    1564		free_signal_struct(p->signal);
    1565bad_fork_cleanup_sighand:
    1566	__cleanup_sighand(p->sighand);
    1567bad_fork_cleanup_fs:
    1568	exit_fs(p); /* blocking */
    1569bad_fork_cleanup_files:
    1570	exit_files(p); /* blocking */
    1571bad_fork_cleanup_semundo:
    1572	exit_sem(p);
    1573bad_fork_cleanup_audit:
    1574	audit_free(p);
    1575bad_fork_cleanup_perf:
    1576	perf_event_free_task(p);
    1577bad_fork_cleanup_policy:
    1578#ifdef CONFIG_NUMA
    1579	mpol_put(p->mempolicy);
    1580bad_fork_cleanup_threadgroup_lock:
    1581#endif
    1582	if (clone_flags & CLONE_THREAD)
    1583		threadgroup_change_end(current);
    1584	delayacct_tsk_free(p);
    1585	module_put(task_thread_info(p)->exec_domain->module);
    1586bad_fork_cleanup_count:
    1587	atomic_dec(&p->cred->user->processes);
    1588	exit_creds(p);
    1589bad_fork_free:
    1590	free_task(p);
    1591fork_out:
    1592	return ERR_PTR(retval);
    }
    

    copy_process主要完成了dup_task_struct的调用来复制父进程的进程描述符和初始化子进程内核栈

    static struct task_struct *dup_task_struct(struct task_struct *orig)
    306{
    307	struct task_struct *tsk;
    308	struct thread_info *ti;
    309	int node = tsk_fork_get_node(orig);
    310	int err;
    311
    312	tsk = alloc_task_struct_node(node);
    313	if (!tsk)
    314		return NULL;
    315
    316	ti = alloc_thread_info_node(tsk, node);
    317	if (!ti)
    318		goto free_tsk;
    319
    320	err = arch_dup_task_struct(tsk, orig);
    321	if (err)
    322		goto free_ti;
    323
    324	tsk->stack = ti;
    325#ifdef CONFIG_SECCOMP
    326	/*
    327	 * We must handle setting up seccomp filters once we're under
    328	 * the sighand lock in case orig has changed between now and
    329	 * then. Until then, filter must be NULL to avoid messing up
    330	 * the usage counts on the error path calling free_task.
    331	 */
    332	tsk->seccomp.filter = NULL;
    333#endif
    334
    335	setup_thread_stack(tsk, orig);
    336	clear_user_return_notifier(tsk);
    337	clear_tsk_need_resched(tsk);
    338	set_task_stack_end_magic(tsk);
    339
    340#ifdef CONFIG_CC_STACKPROTECTOR
    341	tsk->stack_canary = get_random_int();
    342#endif
    343
    344	/*
    345	 * One for us, one for whoever does the "release_task()" (usually
    346	 * parent)
    347	 */
    348	atomic_set(&tsk->usage, 2);
    349#ifdef CONFIG_BLK_DEV_IO_TRACE
    350	tsk->btrace_seq = 0;
    351#endif
    352	tsk->splice_pipe = NULL;
    353	tsk->task_frag.page = NULL;
    354
    355	account_kernel_stack(ti, 1);
    356
    357	return tsk;
    358
    359free_ti:
    360	free_thread_info(ti);
    361free_tsk:
    362	free_task_struct(tsk);
    363	return NULL;
    364}
    365
    366#ifdef CONFIG_MMU
    

    copy_thread完成内核栈关键信息初始化

    int copy_thread(unsigned long clone_flags, unsigned long sp,
    133	unsigned long arg, struct task_struct *p)
    134{
    135	struct pt_regs *childregs = task_pt_regs(p);
    136	struct task_struct *tsk;
    137	int err;
    138
    139	p->thread.sp = (unsigned long) childregs;
    140	p->thread.sp0 = (unsigned long) (childregs+1);
    141	memset(p->thread.ptrace_bps, 0, sizeof(p->thread.ptrace_bps));
    142
    143	if (unlikely(p->flags & PF_KTHREAD)) {
    144		/* kernel thread */
    145		memset(childregs, 0, sizeof(struct pt_regs));
    146		p->thread.ip = (unsigned long) ret_from_kernel_thread;
    147		task_user_gs(p) = __KERNEL_STACK_CANARY;
    148		childregs->ds = __USER_DS;
    149		childregs->es = __USER_DS;
    150		childregs->fs = __KERNEL_PERCPU;
    151		childregs->bx = sp;	/* function */
    152		childregs->bp = arg;
    153		childregs->orig_ax = -1;
    154		childregs->cs = __KERNEL_CS | get_kernel_rpl();
    155		childregs->flags = X86_EFLAGS_IF | X86_EFLAGS_FIXED;
    156		p->thread.io_bitmap_ptr = NULL;
    157		return 0;
    158	}
    159	*childregs = *current_pt_regs();
    160	childregs->ax = 0;
    161	if (sp)
    162		childregs->sp = sp;
    163
    164	p->thread.ip = (unsigned long) ret_from_fork;
    165	task_user_gs(p) = get_user_gs(current_pt_regs());
    166
    167	p->thread.io_bitmap_ptr = NULL;
    168	tsk = current;
    169	err = -ENOMEM;
    170
    171	if (unlikely(test_tsk_thread_flag(tsk, TIF_IO_BITMAP))) {
    172		p->thread.io_bitmap_ptr = kmemdup(tsk->thread.io_bitmap_ptr,
    173						IO_BITMAP_BYTES, GFP_KERNEL);
    174		if (!p->thread.io_bitmap_ptr) {
    175			p->thread.io_bitmap_max = 0;
    176			return -ENOMEM;
    177		}
    178		set_tsk_thread_flag(p, TIF_IO_BITMAP);
    179	}
    180
    181	err = 0;
    182
    183	/*
    184	 * Set a new TLS for the child thread?
    185	 */
    186	if (clone_flags & CLONE_SETTLS)
    187		err = do_set_thread_area(p, -1,
    188			(struct user_desc __user *)childregs->si, 0);
    189
    190	if (err && p->thread.io_bitmap_ptr) {
    191		kfree(p->thread.io_bitmap_ptr);
    192		p->thread.io_bitmap_max = 0;
    193	}
    194	return err;
    195}
    


    实验过程:


    代码调试中的问题和解决过程

    • 问题1:
    • 问题1解决方案:登录之后下载还是不成功,用浏览器手动开网址可能受网速影响不稳定大部分时间都404页面
      于是在网站下载了fork的代码在原来的menu下修改了test.c
    • 问题2:
      调试过程中段点ret_from_fork没有停
    • 问题2解决方案:单步设置断点跟踪

  • 相关阅读:
    SQL Server2000的ROWGUID 列
    数据库主键设计之思考
    SQL Server 索引结构及其使用(四)
    一些基础表单的验证 函数
    JS加密编码算法
    textarea自动增高并隐藏滚动条
    HTML之打开/另存为/打印/刷新/查看原文件等按钮的代码
    Code Snippets
    jQuery验证框架
    Jquery 扩展验证
  • 原文地址:https://www.cnblogs.com/20189224sxy/p/10017376.html
Copyright © 2020-2023  润新知