[LUGOS-PROG] Bash si sladak

Borut Mrak b at aufbix.org
Tue Mar 19 21:39:07 CET 2002


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On Tuesday 19 March 2002 20:04, you wrote:
> Tisti, ki vam random ne vraca nakljucnih stevil, poskusite se tole:
>
>   for ((i=1; i<5 ; i++)); do echo $RANDOM; sleep 1; done  | cat

To nekako v 99% primerov ne pride v postev, ceprav ocitno resi problem...

> Iz kode za bash je videti, kot da je seme za nakljucni generator vsakic
> znova nastavljeno tako, da je pristet se sistemski cas. Sam ne morem
> preprosto preskusiti domneve.

Hmm...jaz sem zdaj posrkal k sebi source od basha. Ze prej sem hotel omenit, 
da je razlika v obnasanju kadar se zadeva pozene v subshellu. Ni torej 
pomemben pipe v drug program, ta "feature" se pojavi tudi ce recimo cel 
expression ovijemo v oklepaje.

V variables.c je tole:

/* The random number seed.  You can change this by setting RANDOM. */
static unsigned long rseed = 1;
static int last_random_value;

int
get_random_number ()
{
  int rv;

  /* Reset for command and process substitution. */
  if (subshell_environment)
    sbrand (rseed + getpid() + NOW);

  do
    rv = brand ();
  while (rv == last_random_value);
  return rv;
}

static SHELL_VAR *
get_random (var)
     SHELL_VAR *var;
{
  int rv;
  char *p;

  rv = get_random_number ();
  last_random_value = rv;
  p = itos (rv);

  FREE (var->value);

  VSETATTR (var, att_integer);
  var->value = p;
  return (var);
}

/* Returns a pseudo-random number between 0 and 32767. */
static int
brand ()
{
  rseed = rseed * 1103515245 + 12345;
  return ((unsigned int)((rseed >> 16) & 32767));       /* was % 32768 */
}

/* Set the random number generator seed to SEED. */
static void
sbrand (seed)
     unsigned long seed;
{
  rseed = seed;
  last_random_value = 0;
}

Problem je torej v tem, da imamo prehitre racunalnike. Ce se zadeva pozene v 
subshellu, potem se random number generator seeda *vsakic* (predvidevam, 
basha ne poznam tako intimno) z isto vrednostjo (   sbrand (rseed + getpid() 
+ NOW); Tale NOW bi se moral spremijat pa je ocitno zmeraj enak  ), ko hocemo 
prebrat kaksno random stevilo. Ker je seveda tale "random" vsakic enak 
(rv==last_random_value), se brand() pozene se enkrat, nato se spet vrne prvi, 
nato se brand() spet pozene 2x...

Tole je povedal povrsen pogled...malo manj povrsen pa ni tako 
preprican...cetudi se tisti sbrand() klice z vsakim klicem 
get_random_number(), kadar smo v subshellu, bi se rseed moral spremenit, saj 
ga nastavi na rseed+getpid()...tole presega moje znanje. Mogoce pa gre za 
kaksno subtilnost s tistimi bitwise operacijami v brand().

lp,

- -- 
Borut, vesel da ni vsakodnevno izpostavljen C-jevskemu mucenju.
b at aufbix.org
- ------------
Sorry I'm late, I'll leave early to make up for it.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.0.6 (GNU/Linux)
Comment: For info see http://www.gnupg.org

iEYEARECAAYFAjyXoesACgkQRUVvbWYRhIKs9QCgySxFzoyzHF/GekcIHtRQLie6
BL8AnRG9AUq3unXs1fDAG9ZKI96yjnve
=h7S0
-----END PGP SIGNATURE-----



More information about the lugos-prog mailing list